三角区域的浮点难度

时间:2016-09-20 08:34:01

标签: c++ floating-point

我的程序创建的输出首先是准确的,然后对于5000000以上的所有答案都变为0。我想知道为什么当我使用我称之为Heron&区域的函数时就是这种情况。

#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的输出?

2 个答案:

答案 0 :(得分:2)

您怀疑这是浮点数的问题。

如果您在a中打印sheron_area,您会注意到它们很快变得相同,使s - a为零。

c远小于a时(也就是说,当你有一个非常&#34;尖的&#34;三角形时,会发生这种情况;当双方为10,000,000时出现零,第三个出现是1)。

将类型更改为double会使问题稍后出现,但它不会消失。

如果您想要处理非常大的差异,则需要重新安排计算。

Wikipedia上的解决方案(由@harold在评论中链接)给出了

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

其中a >= bb >= c,括号是必要的。
是的,你需要担心操作的顺序。

(还有一篇非常详细的文章here,对此解决方案进行了分析。)

答案 1 :(得分:0)

随着函数heron_area中的变量a呈指数级增大和变大,变量c(具有值1.0f的常量)变得越来越不相关。

由于浮点精度有限,表达式为:

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

然后简化为:

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

与:

相同
float s = a;

因此变量s和a具有相同的值,因此表达式为:

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

总是产生0.0f,因为减去s - a的结果是0.0f,并且将零乘以任何值始终为零。