[英]Error in Floating point operation in C
請讓我知道以下C函數之間的區別。
static int mandel(float c_re, float c_im, int count) {
float z_re = c_re, z_im = c_im;
int i;
for (i = 0; i < count; ++i) {
if (z_re * z_re + z_im * z_im > 4.f)
break;
float new_re = z_re*z_re - z_im*z_im;
float new_im = 2.f * z_re * z_im;
z_re = c_re + new_re;
z_im = c_im + new_im;
}
return i;
}
以下
static int mandel(float c_re, float c_im, int count) {
float z_re = c_re, z_im = c_im;
int i;
for (i = 0; i < count; ++i) {
if (z_re * z_re + z_im * z_im > 4.f)
break;
float new_im = 2.f * z_re * z_im;
z_re = c_re + z_re*z_re - z_im*z_im;//I have combined the statements here and removed float new_re
z_im = c_im + new_im;
}
return i;
}
請參閱我對代碼更改的注釋。函數為某些輸入提供不同的值。 由於兩個陳述相結合,浮動是否會被誤解?
在數學中,這兩個陳述是等價的。 但是在計算機硬件中它們可能不是。
您可能會出錯,因為初始結果(new_re)已四舍五入,然后添加到c_re。
正如尼克拉斯所說:
中間值以更高的精度存儲
因此,當存儲到new_re時,new_re的結果可能會丟失一些浮點,但如果將中間值添加到c_re,則較小的c_re值與new_re計算的較低有效值組合可能會導致最終結果。
在計算數學表達式時,允許C或C ++編譯器生成的代碼以更高的精度保持中間結果。
例如,在x86計算機上,C和C ++ double
值通常是64位IEEE754浮點數,但數學處理器堆棧在進行計算時每個值使用80位。
這意味着計算的確切結果將取決於臨時存儲在內存中的位置以及將其保存在fp堆棧中的位置。 通常這不是問題,因為臨時值的精度高於存儲值的精度......但這並不總是正確的,因為計算可能是圍繞浮點預期舍入規則設計的。
另請注意,編譯器提供特殊標志以要求對數學評估嚴格要求或允許它們非常自由地幫助優化(包括忽略將操作存儲到局部變量或將操作重寫為理論數學等效版本)。 今天的默認通常是有點自由,而不是非常嚴格,因為這會損害性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.