2016-09-20 245 views
2

我的程序創建的輸出首先是準確的,然後在5000000以上的所有答案變成0。我想知道爲什麼這是這種情況,當我使用函數我稱之爲蒼鷺的面積。三角形面積的浮點難度

#include "stdafx.h" 
#include "stdlib.h" 
#include <iostream> 
#include <math.h> 
#include <stdio.h> 

float heron_area(float a, float c) { 
    float s = (a + a + c)/2.0f; 
    return (s - a)*sqrtf(s*(s - c)); 
} 


int main(void) { 
    int j = 18; 
    float i = 10; 
    for (int k = 0; k < j; k++){ 
     float g = i * 10; 
     std::cout << heron_area(g, 1) << std::endl; 
     i = g; 
} 


return 0; 
} 

這可能與使用浮點數的問題有關。爲什麼在最後一次輸出500000後得到0的輸出?

+1

使用double來代替浮動 – seccpur

+1

這個問題是衆所周知的[解決方案在維基百科上](https://en.wikipedia.org/wiki/Heron%27s_formula#Numerical_stability) – harold

回答

2

這是浮點數的問題,因爲你懷疑。

如果您在heron_area中打印as,您會注意到它們非常快速地變爲相同,使得s - a爲零。

發生這種情況時c遠小於a(也就是說,當你有一個非常「尖的」三角形;當兩邊是10,000,000,第三個是1時出現零)。

將類型更改爲double會使問題稍後出現,但不會消失。

如果你想處理幅度的巨大差異,你需要重新排列你的計算。

有,讓

Area = 0.25 * sqrt((a+(b+c)) * (c-(a-b)) * (c+(a-b)) * (a+(b-c))) 

其中a >= bb >= cWikipedia溶液(通過在註釋中@harold鏈接),和括號內是必要的。
是的,你需要擔心操作的順序。

(而且有一個非常詳細的文章here與此解決方案的分析。)

0

如在函數heron_area變量a的增長成指數大,變量c,其是恆定的,與所述值1.0f ,變得越來越不相關。

由於浮點的精確度有限的表達:

float s = (a + a + c)/2.0f; 

然後簡化爲:

float s = (a + a)/2.0f; 

這是一樣的:

float s = a; 

因此變量小號和a具有相同的值,所以表達式:

return (s - a)*sqrtf(s*(s - c)); 

總是產生0.0f,作爲減去s - a0.0f,並乘以零被任何東西總是零的結果。