繁体   English   中英

c ++不正确的浮点运算

[英]c++ incorrect floating point arithmetic

对于以下程序:

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    for (float a = 1.0; a < 10; a++)
        cout << std::setprecision(30) << 1.0/a << endl;
    return 0;
}

我收到以下输出:

1
0.5
0.333333333333333314829616256247
0.25
0.200000000000000011102230246252
0.166666666666666657414808128124
0.142857142857142849212692681249
0.125
0.111111111111111104943205418749

对于较低位的数字,这绝对不是正确的,特别是对于1 / 3,1 / 5,1 / 7和1/9。 事情刚开始出错10 ^ -16我希望看到更多类似的东西:

1
0.5
0.333333333333333333333333333333
0.25
0.2
0.166666666666666666666666666666
0.142857142857142857142857142857
0.125
0.111111111111111111111111111111

这是float类中的继承缺陷吗? 有没有办法克服这个并进行适当的划分? 是否有用于执行精确十进制运算的特殊数据类型? 在我的例子中,我只是做了一些愚蠢或错误的事情吗?

计算机无法表示很多数字,即使您使用浮点数或双精度浮点数也是如此。 1/3,或.3重复,是这些数字之一。 所以它只是尽力而为,这就是你得到的结果。

请参阅http://floating-point-gui.de/或google float precision,这里有大量的信息(包括许多SO问题)。

回答你的问题 - 是的,这是float类和double类的固有限制。 一些数学程序(MathCAD,可能是Mathematica)可以进行“符号”数学运算,从而可以计算出“正确”的答案。 在许多情况下,即使在非常复杂的计算中也可以管理舍入误差,使得前6-8位小数是正确的。 然而,情况恰恰相反 - 可以构建天真的计算,返回非常不正确的答案。

对于像整数除法这样的小问题,你会获得相当数量的小数位精度(可能是4-6位)。 如果你使用双精度浮点数,那么可能会达到8个。如果你需要更多...好吧,我会开始质疑为什么你需要那么多小数位。

首先,由于你的代码是1.0/a ,它给你double1.0double值, 1.0ffloat )因为C ++(和C)的规则总是将较小的类型扩展为较大的类型,如果操作数为一个操作是不同的大小(因此, int + char在添加值之前将char变为intlong + int将使int长等等)。

第二个浮点值具有“数字”的设定位数。 在float中,即23位(+ 1'隐藏'位),并且在double中它是52位(+1)。 然而,每位得到大约3位数(正好:log2(10),如果我们使用十进制数表示),所以23位数字给出大约7-8位数字,53位数字大约16-17位数字。 剩下的只是“噪音”,由转换为十进制数字后数字的最后几位引起。

要具有无限精度,我们必须将值存储为分数,或者具有无限数量的位。 当然,我们可以有一些其他有限的精度,比如100位,但我相信你也会抱怨它,因为它会在“出错”之前再有15个左右的数字。

浮点只有很高的精度(23位值得精确)。 如果你真的想看到“0.333333333333333333333333333333”输出,你可以创建一个自定义的“分数”类,它分别存储分子和分母。 然后,您可以完全准确地计算任何给定点的数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM