歷史問題
對浮點數處理,涉及編譯器、硬件等對浮點數2進製表示的細節不一致,都有可能,對同一輸入的浮點數計算,產生不一樣的結果。git
可是若是你願意作大量的工做,讓你的編譯器「嚴格」符合IEEE 754編譯模型以及限制你所使用的浮點數操做的集合,你或許可讓不一樣的編譯器和不一樣架構的機器能都對浮點數計算獲得徹底一致的結果。這一般會致使顯著下降浮點計算的性能github
以上摘至 遊戲網絡開發(五):浮點數的肯定性ubuntu
代碼驗證
void myprintf(int i, double valf);網絡
double test_sin(double val)
{
return sin(val);
}架構
void test_normal(int count)
{
double valf = 0.25;
myprintf(-1, valf);
for (int i = 0; i < count; i++)
{
valf = test_sin(valf);
myprintf(i, valf);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上述代碼,好比調用 test_normal(20),在window、ubuntu上的結果以下:函數
能夠看到從第14運算開始, 2邊的值在內存中已經開始有誤差了。性能
那麼如何保證浮點數計算一致呢?測試
可使用整數類型代替浮點數。.net
libfixmath
github地址:https://github.com/PetteriAimonen/libfixmathorm
該庫使用整數類型代替浮點數,原理搜關鍵字Q16.16
下面是使用libfixmath修改上面代碼的例子:
void myprintf(int i, double valf);
Fix16 test_sin_by_fix16(Fix16 val)
{
return val.sin();
}
void test_by_fix16(int count)
{
Fix16 valf(double(0.25));
myprintf(-1, valf);
for (int i = 0; i < count; i++)
{
valf = test_sin_by_fix16(valf);
myprintf(i, valf);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
把上述代碼,好比調用 test_by_fix16(20),在window、ubuntu上的結果以下:
能夠看到紅色框內的在window、ubuntu上的結果一致。
float陷阱
浮點數的計算不肯定性,使用double比較容易暴露出來。
實測過float類型,在window、ubuntu、華爲mate9上均計算一致。
所以,當心本身代碼、第3方代碼中float類型
庫定點化
由上面 libfixmath 的使用例子,能夠看出,基本上只要替換 double/float 類型 爲 Fix16 類型,並保證編譯經過。
libfixmath提供了一系列定點化數學函數,包括:
加、減、乘、除
大於、等於、小於等比較運算符
sin、asin等三角函數
sqrt 開根號
若是涉及定點矩陣運算,可使用:https://github.com/PetteriAimonen/libfixmatrix
而後,就是功能測試,確保庫功能正常。
例子代碼 詳細例子代碼,請參考: https://github.com/fananchong/test_fixint ———————————————— 版權聲明:本文爲CSDN博主「fananchong2」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/u013272009/article/details/80169013