C++ c++;不正确的浮点运算
对于以下程序:C++ c++;不正确的浮点运算,c++,floating-point,division,C++,Floating Point,Division,对于以下程序: #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/3、
#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/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重复就是这些数字之一。所以它只是尽了最大的努力,这就是你得到的结果 你看,或者谷歌的float precision,关于这个主题有很多信息(包括很多问题) 回答您的问题——是的,这是float类和double类的固有限制。一些数学程序(MathCAD,可能是Mathematica)可以进行“符号”数学,从而计算“正确”答案。在许多情况下,舍入误差是可以控制的,即使在非常复杂的计算中也是如此,因此小数点后6-8位是正确的。然而,事实正好相反——可以构造出返回错误答案的幼稚计算
对于像整数除法这样的小问题,您将获得相当高的小数点精度(可能是4-6位)。如果使用双精度浮点,则可能会达到8。如果你需要更多。。。好吧,我开始质疑你为什么需要这么多的小数位。浮点只有这么高的精度(精确到23位)。如果您确实想看到“0.333333”输出,可以创建一个自定义的“分数”类,分别存储分子和分母。然后你就可以完全准确地计算出任何给定点的数字首先,由于您的代码执行了<代码> 1 /a <代码>,它给出了<代码>双< /代码>(<代码> 1 < /COD>是一个代码>双值,<代码> 1.0f <代码>浮点< /代码>,因为如果操作的操作数不同,则C++(和C)的规则总是将较小的类型扩展到较大的类型。(因此,
int
+char
在添加值之前将char
变成int
,long
+int
将使int
变长,等等)
第二个浮点值有一组“数字”的位数。在浮点值中,这是23位(+1“隐藏”位),在双精度值中是52位(+1)。但每位大约得到3位数字(如果我们使用十进制数字表示,则精确地说是log2(10)),所以一个23位的数字大约是7-8位,一个53位的数字大约是16-17位。剩下的只是数字的最后几位在转换成十进制数字时没有消失而产生的“噪音”
要获得无限精度,我们要么将值存储为分数,要么存储为无限位数。当然,我们可以有其他有限精度,比如100位,但我相信你也会对此抱怨,因为它在“出错”之前只会有另外15位左右.猜猜它们的最大精度是多少。你希望浮点运算能做什么?我在问题中说它们的最大精度是10^-16,我希望得到我在最后列出的那种输出,尽管基于这些问题,我猜你们会指出我在重载数据类型,我将问这个问题感觉很愚蠢。浮点数就像科学记数法一样,精度约为6.92位小数。
double
可以让您获得约15.65位小数。如果您想要完美的精度,您需要一个特殊的rational
类,这个类很大而且速度很慢。精度的小数位是在内部,它是二进制的,float
精确到23位二进制数字,double精确到53位二进制数字。尝试打印std::numeric\u limits::digits10
对于T
=float
,double
和long double
,以获得至少合理的精度位数近似值你可以分别从你的实现的float
、double
和long double
中得到期望值。他的输出精确到~53位是有原因的,但你的观点是正确的。感谢你提供的信息,至于我为什么需要这么多小数位,是因为我正在从事一个项目,我需要识别长的序列这就是为什么直到今天我才担心精度的原因。@eldersouth在这种情况下,这是一个只涉及整数和整数运算的问题。使用浮点数是错误的(带任意精度整数的实数有理数可能是一种选择,但普通机器int
算法是最简单也是最好的方法)。我很确定,识别重复序列可以通过使用“长除法”来完成,就像用手将12341除以73(或10除以7,等等)一样[编辑:这可以在整数数学中完成]同意Mats的观点——用“手工”完成可能是解决您特定问题的最佳策略!+1推荐,而不是另一个长文档。@MooingDuck:事实上,我是从我的记忆中提取的,这显然也是一团糟。现在已修复。剩余部分不完全是噪声。Float应该有6个准确数字,然后下一个数字通常是准确的,有8%的几率为0f被关1。(当然,除非它滚动,导致前面的数字被四舍五入)。@MooingDuck:不,我的意思是,当你取最后一个“准确”的十进制数字时,下一个数字将只提供一个部分数字,而数字的剩余部分是试图继续时产生的噪音
1
0.5
0.333333333333333333333333333333
0.25
0.2
0.166666666666666666666666666666
0.142857142857142857142857142857
0.125
0.111111111111111111111111111111