这仅仅是一个实验的问题!
没有必要回答,请不要投赞成票。这既不是
我的
问题也不
我的
答案,但只有一个例子更好,更方便,更可用的FAQ,塞满了广告。
常见问题:为什么0.3 - 0.2 - 0.1不等于零吗?
257(30天)
显示旧的评论
更多的答案(2)
约翰D 'Errico
2021年8月30日
编辑:约翰D 'Errico
2021年8月30日
让我添加的问题。
假设我们试图以二进制形式表示这些数字吗?代表1/10 = 0.1小数,但作为一个二进制数?我们必须这样做,因为所有的浮点数存储在二进制形式。即使使用十进制存储,我们仍然会有问题。例如,2/3 - 1/3 = = 1/3吗?当然在小数运算必须这样吗?
假设我们上工作10位精度的小数运算存储形式。将1/3是什么样子的呢?
X = 0.3333333333
Y = 0.6666666667
我的两个值接近我能找到的小数形式,只有10位数后点。现在x将:
Y - X = 0.6666666667 - 0.3333333333 = 0.3333333334
这不是相同的值x,但你说,我应该使用Y = 0.6666666666,四舍五入。然后我们会X = X。
但是我们还必须X + Y = 3/3 = 1。如果我们有圆形Y使最后的结果,然后我们会看到:
X = Y = 0.3333333333 + 0.6666666666 = 0.9999999999
所以总是会有一些矛盾,只要我们被迫使用一个有限小数存储没有有限的数字表示的基础。
这同样适用于任何二进制存储形式。这是双打和单打是如何存储在MATLAB。双重使用52二进制比特存储数量。MATLAB是尽可能接近,但只有52位表示尾数。
所以二进制数1/10会是什么样子?如果我们认为的二进制比特是这样的:
0.00011001100110011001100110011001100110011001100110011……
这是……
1/10 = 2 ^ 4 + 2 ^ 5 + 2 ^ 8 + 2 ^ 9 + 2 ^ -12 + 2 ^ -13 + 2 ^ -16 + 2 ^ -17 +…
试一试!
格式长g
2 ^ 4 + 2 ^ 5 + 2 ^ 8 + 2 ^ 9 + 2 ^ -12 + 2 ^ -13 + 2 + 2 ^ -16年^ -17
我不得不停止的地方。如果我加入一些条款,我们将更接近。事实上,MATLAB使用的二进制扩张1/10的数量是:
约= (2。^ [4 5 8 9 -12 -13 -16 -17 -20 -21 -24 -25 -28 -29 -32 -33 -36 -37 -40 -41 -44 -45 -48 -49 -52 -53 -55])
看起来像由MATLAB 0.1显示但它吗?精确到0.1吗?
sprintf (' % 0.55 f '约)
sprintf (' % 0.55 f ',1/10)
正如您可以看到的,现在两个值是一样的。但无论是exaclty 0.1,唯一能找到的最接近的近似MATLAB数字。
同样的,我们可以尝试近似0.2和0.3作为二进制数字,但再一次,我们将会失败,只要我们被迫使用有限数量的二进制位的近似。当我们看到小数点例子之前,我们总是失败的一些时间。有时,事情的工作。例如,试试这两个例子:
0.2 - 0.1 = = 0.1
0.3 - 0.2 = = 0.1
所以那些琐碎的数学身份似乎工作,但是其他的失败。问题是,MATLAB只能使用有限数量的比特来表示任意数量。当这些数字是完全不能表示的有限数量的部分,我们将总是有时我们期望看到一个矛盾必须是真实的。
这不会发生所有的时间。例如,什么是表示在MATLAB数量1/8 = = 0.125 ?
sprintf (' % 0.55 f ',1/8)
所以MATLAB得到完全正确的。关键是,1/8是2的幂。这正是以二进制形式表示的。这意味着我们将看到这个总是在MATLAB工作:
1/2 - 1/8 = = 3/8
简单的正面或负面的力量2(其中整数倍)将正确地表示,只要有限数量的比特足以完成这项工作。但0.1,0.2,和0.3吗?有限可表示的是小数,在二进制并非如此。这是我承担为什么在MATLAB 0.3 -0.2 -0.1不等于零。
0评论
沃尔特·罗伯森
2022年6月29日
考虑任何有限长按位记数法固定基地,b .例如,10为底和0.193意义1 * 10 ^ 1 + 9 * 10 ^ 2 + 3 * 10 ^ 3,或者换句话说,(1 * 10 ^ 2 + 9 * 10 ^ 1 + 3 * 10 ^ 0)/ 10 ^ 3。193/10 ^ 3。
考虑一个在0和1之间。假设我们可以有理分式,表达一个整数N除以M数字的基地,N / B ^ M。现在数量是1除以一个数
互质
B、N / B ^ M = 1 / P, N整数0 (B ^ M - 1)。例如,3是互质,所以10 ^ N / M = 1 / 3是一个示例。
现在,分母交叉相乘得到N = B ^ M / P。但是我们的假设是B和P相对',所以我们知道不能完全除以B ^ M P。
因此,对于
任何
有限长度M固定整数基B,存在数字(有理数甚至!)不能
完全
代表的基础。在上一个示例中,1/3不能完全代表在任何固定长度的小数位数;1/7或1/11或1/13也不能……
现在,我们基本是2,相对主要是10。N = 2 ^ 10 M /不能工作,
任何
有限数量的数字。除了2 ^ 0没有2的幂这正是10整除。
因此,不可能有限以2为底的位置表示1/10(或1/100或1/1000)。所以只要你使用有限的二进制表示,0.001(基地10)不能
完全
等于1/1000。所以当你0.001有限位置来表示二进制乘以350,你永远不会得到
完全
350/1000。
问题就变成了你的价值
做
得到350 * 0.001是相同的近似,得到写作0.350。答案是没有。如果它是相同的,这是偶然,会有不同的数字未能解决。
给出任何特定的舍入系统,即使任何固定数量的额外“警卫”位数乘法,可以表明,只要你是用一个有限的位置整数基本系统,会有这样的情况下,圆形表示乘法后不会平等。
我强调,这不是一个MATLAB错误:这是一个固有的问题
每一个
有限的位置integer-base数字系统。
你可以
减少
问题如果你立即切换indefinite-precision有理数和执行计算的一切理性,但(A)这将需要越来越多的大量的记忆你经历的计算;和(B)它不会完全解决问题。(例如,如果用户写0.3333333333然后他们“意愿”编写合理的1/3,还是“意愿”写rational 3333333333/10000000000 ?)
MATLAB选择有限的二进制表示,因为那是你的计算机硬件的用途。