常见问题:为什么0.3 - 0.2 - 0.1不等于零吗?

257(30天)
1月
1月 2012年12月26日
回答: 沃尔特·罗伯森 2022年6月29日
为什么
0.3 - 0.2 - 0.1 = = 0
v = 0:0.1:1;
任何(v = = 0.3)
(或类似的数字)的答复 吗?
1评论
1月
1月 2012年12月26日
编辑:1月 2012年12月26日
这仅仅是一个实验的问题! 没有必要回答,请不要投赞成票。这既不是 我的 问题也不 我的 答案,但只有一个例子更好,更方便,更可用的FAQ,塞满了广告。

登录置评。

接受的答案

1月
1月 2012年12月26日
编辑:1月 2012年12月26日
0.3 - 0 - 2 - 0.1 返回 -2.7756 e-17
经常提到的新闻组,一些浮点数不能完全以二进制形式表示。这就是为什么你看到非常小的但是不为零的结果。看到每股收益。
所不同的是,0:0.1:0.4增量的数量非常接近但不是0.1下面提到的原因。所以就几步后而[0 0.1 0.2 0.3 0.4]迫使数量适当的价值,尽可能准确地表示。
一个= [0 0.1 0.2 0.3 0.4];
b = 0: 1。:。4;
= sprintf (“% 20.18 f \ n”,)
> > =
0.000000000000000000% = =
0.100000000000000010% = =
0.200000000000000010% = =
0.299999999999999990% ~ = b !
0.400000000000000020% = =
b = sprintf (“% 20.18 f \ n”,b)
> > b =
0.000000000000000000% = =
0.100000000000000010% = =
0.200000000000000010% = =
0.300000000000000040% ~ =,!
0.400000000000000020% = =
和:
格式十六进制;
高清= (。b。)
> >高清=
0000000000000000 0000000000000000% = =
3 fb999999999999a fb999999999999a% = =
3 fc999999999999a fc999999999999a% = =
3 fd3333333333333 fd3333333333334% ~ = !
3 fd999999999999a fd999999999999a% = =
如果你想比较两个浮点数,很小心使用= =。另一种比较方法是检查如果你比较的两个数字是“接近”(公差)表达的:
%,而不是= = b
%使用:
< tol areEssentiallyEqual = abs (a - b)
%对某些小托尔的价值相对于a和b
%也许使用eps (a)定义和/或eps (b)
你可以看到同样的行为在MATLAB。使用铅笔和纸(或黑板、白板等)计算x = 1/3你想要尽可能多的小数位。小数点后的数量必须是有限的,然而。现在计算y = 3 * x。在确切的算术,y是完全1;然而,由于x不是三分之一但近似是一个圆形的三分之一,y不会完全1。
可读的介绍了浮点运算,看看克里夫的角落从1996条浮动点(PDF) //www.tatmou.com/company/newsletters/news_notes/pdf/Fall96Cleve.pdf
对浮点运算更为严格和详细的信息,阅读下面的纸:每台计算机科学家应该知道浮点运算 http://docs.sun.com/source/806-3568/ncg_goldberg.html
另一个资源是Technical Note 1108 //www.tatmou.com/金宝appsupport/tech-notes/1100/1108.html 上的支持部分M金宝appathWorks网站。
5个评论
沃尔特·罗伯森
沃尔特·罗伯森 2021年8月30日
128位表示范围没有改变,错误将6 e-36,但不是0。

登录置评。

更多的答案(2)

约翰D 'Errico
约翰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
ans =
0.0999984741210938
我不得不停止的地方。如果我加入一些条款,我们将更接近。事实上,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])
约=
0.1
看起来像由MATLAB 0.1显示但它吗?精确到0.1吗?
sprintf (' % 0.55 f '约)
ans =“0.1000000000000000055511151231257827021181583404541015625”
sprintf (' % 0.55 f ',1/10)
ans =“0.1000000000000000055511151231257827021181583404541015625”
正如您可以看到的,现在两个值是一样的。但无论是exaclty 0.1,唯一能找到的最接近的近似MATLAB数字。
同样的,我们可以尝试近似0.2和0.3作为二进制数字,但再一次,我们将会失败,只要我们被迫使用有限数量的二进制位的近似。当我们看到小数点例子之前,我们总是失败的一些时间。有时,事情的工作。例如,试试这两个例子:
0.2 - 0.1 = = 0.1
ans =逻辑
1
0.3 - 0.2 = = 0.1
ans =逻辑
0
所以那些琐碎的数学身份似乎工作,但是其他的失败。问题是,MATLAB只能使用有限数量的比特来表示任意数量。当这些数字是完全不能表示的有限数量的部分,我们将总是有时我们期望看到一个矛盾必须是真实的。
这不会发生所有的时间。例如,什么是表示在MATLAB数量1/8 = = 0.125 ?
sprintf (' % 0.55 f ',1/8)
ans =“0.1250000000000000000000000000000000000000000000000000000”
所以MATLAB得到完全正确的。关键是,1/8是2的幂。这正是以二进制形式表示的。这意味着我们将看到这个总是在MATLAB工作:
1/2 - 1/8 = = 3/8
ans =逻辑
1
简单的正面或负面的力量2(其中整数倍)将正确地表示,只要有限数量的比特足以完成这项工作。但0.1,0.2,和0.3吗?有限可表示的是小数,在二进制并非如此。这是我承担为什么在MATLAB 0.3 -0.2 -0.1不等于零。

沃尔特·罗伯森
沃尔特·罗伯森 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选择有限的二进制表示,因为那是你的计算机硬件的用途。

类别

找到更多的在小学数学帮助中心文件交换

社区寻宝

找到宝藏在MATLAB中央,发现社区如何帮助你!

开始狩猎!