2016-09-20 110 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,并乘以零被任何东西总是零的结果。