为什么2个双值之间的差值计算错误?[重复]

问题描述 投票:0回答:1

我需要计算两个字符串之间的差值,只取第一个精度。我必须先转换成双倍数,然后再计算差值,如下所示

#include <iostream>
#include <math.h>
#include <string>

using namespace std;

int main()
{
    string v1 = "1568678435.244555";
    string v2 = "1568678435.300111";

    double s1 = atof(v1.substr(0,12).c_str());  // take upto first precision and convert to double
    double s2 = atof(v2.substr(0,12).c_str());  // take upto first precision and convert to double
    std::cout<<s1<<" "<<s2<<" "<<s2-s1<<endl;
    if (s2-s1 >= 0.1)
        cout<<"bigger";
    else
        cout<<"smaller";

    return 0;
}

我希望计算结果是 1568678435.3 - 1568678435.2 = 0.1 . 但这个程序返回的是这个值。

1.56868e+09 1.56868e+09 0.0999999                                                                               
smaller

为什么会这样,如何正确地得到我想要的值?

c++ floating-point double calculation
1个回答
4
投票

浮点格式的精度有限。并非所有的值都可以表示。例如,数字1568678435.2是不可表示的(IEEE-754二进制64格式)。最接近的可表示值是

1568678435.2000000476837158203125

1568678435. 3也不是一个可表示的值。最接近的可代表值是:1568678435.3也不是一个可代表值。

1568678435.2999999523162841796875

既然你开始使用的浮点值不精确 那么计算结果也不精确也就不足为奇了。减去这些数字的浮点结果是:。

0.099999904632568359375

非常接近0. 1,但不完全是。计算的误差是:。

0.000000095367431640625

还要注意0. 1本身不是一个可表示的数字 所以无论你的输入是什么,都无法得到浮点运算的结果。


如何正确地得到我想要的值?

要想打印出0.1的值,只需将输出结果四舍五入到一个足够粗的精度即可。

std::cout << std::fixed << std::setprecision(1) << s2-s1;

只要计算的误差不超过所需精度的一半就可以了。

如果你不想在计算中处理任何精度误差,那么你一定不要使用浮点数字。


0
投票

你应该将数值之间的差值四舍五入。

if (round((s2-s1) * 10) >= 1)
    cout<<"bigger";
else
    cout<<"smaller";
© www.soinside.com 2019 - 2024. All rights reserved.