您當前的位置:首頁 > 攝影

記錄數值計算中遇到的坑 - 舍入誤差

作者:由 扶搖而上 發表于 攝影時間:2022-09-04

今天突然發現不同並行核數下的計算結果竟然有差異!這種不可復現的問題必然是不能允許的(某生物學院士論文居然不可復現。。。)。掐指一算,已經是第二次掉進舍入誤差這個坑裡了。

1。 舍入誤差的影響

由於計算機中用有限位數的浮點數儲存實數,導致儲存值與真實值存在差異,這便是舍入誤差。這將會帶來什麼影響呢?以一段程式碼為例

static void Main(string[] args)

{

float floatSum1 = 0, floatSum2 = 0;

for (int n = 1; n <= 10000; n++)//第一種順序:從1開始加到10000

{

floatSum1 += 1f / (n * n);//f表示數字1為float型

}

for (int n = 10000; n >= 1; n——)//第二種順序,從10000開始加到1

{

floatSum2 += 1f / (n * n);

}

Console。WriteLine(floatSum1);

Console。WriteLine(floatSum2);

//輸出結果為:

//1。6447253

//1。644834

}

這告訴我們,由於計算順序不一致,得到的結果可能有差異!

2。 消除舍入誤差

在平行計算中,有時很難控制計算順序,那麼只能提高精度了。

static void Main(string[] args)

{

double doubleSum1 = 0, doubleSum2 = 0;

for (int n = 1; n <= 10000; n++)//第一種順序:從1開始加到10000

{

doubleSum1 += 1。0 / (n * n);

}

for (int n = 10000; n >= 1; n——)//第二種順序,從10000開始加到1

{

doubleSum2 += 1。0 / (n * n);

}

Console。WriteLine((float)doubleSum1);

Console。WriteLine((float)doubleSum2);

//輸出結果為:

//1。644834

//1。644834

}

這樣做,並行中計算結果一致性也能保證了。

分割線——————-

更好的解決方法可以百度 Kahan演算法

標簽: 10000  舍入  float  int  console