python中的减法有问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python中的减法有问题相关的知识,希望对你有一定的参考价值。

python中1.2-1为什么不是0.2呢,求大侠指点一二,谢谢!!!!

【造成这个问题的原因分析】:在计算机中,所有的数都是二进制保存,十进制的小数在和二进制数字相互转化的时候,就会出现误差,也就是浮点数的精确度。由于浮点数的精确度不可能完全精准,所以出现这样的情况在所难免。所以会出现问题的截图中所示的状态。

【解决方法】:可以通过将小数减法变为整数减法降低误差。如下图所示:

参考技术A 首先,[问题的成因]:因为计算机中的数都是以二进制存储的,十进制的某些小数是无法用有穷个二进制表示的,于是就出现了这样的问题。比如 0.1+0.2就得不到正确的结果。
其次,[为什么C,C++看起来结果是对的]:精度!还是精度的问题!你在C语言中使用的是格式化输出比如%f,这种格式化输出默认采用的四舍五入策略,导致它看上去似乎是对的!如果你用%.30f你就会发现问题了。
最后,[怎么解决问题]:首先将因子乘以10的N次方得到整数,计算之后再除以10的N次方。
比如 计算 0.1 + 0.2 转换为 (0.1*10 + 0.2*10)/10本回答被提问者和网友采纳
参考技术B 应该说计算机中实际运算的数都会转成二进制数进行真正运算,
那么1.2实际的二进制数是多少?是1.00110011.......,
所以1.2-1之后的二进制数是0.00110011.......,
然后再将这个二进制数转换成十进制等于2^(-3)+2^(-4)+2^(-7)+2^(-8)+......
最后根据py本身对浮点数的限制就显示为0.19999999999999996追问

那为什么在C和C++里面就会是0.2呢

参考技术C 有趣的问题,这个问题说起来也简单,在计算机数字都是用二进制来表示的,而十进制小数用二进制来表示在很多情况下就和十进制不能完全吻合,所以会有很小的误差,为了解决这个问题可以明示我们需要十进制

from decimal import *
Decimal(1.2)-Decimal(1)

详细具体的应用可以看
help()
decimal追问

那为什么在C和C++里面就会是0.2呢

追答

关于C可以参考nikoloss的回答

[为什么C,C++看起来结果是对的]:精度!还是精度的问题!你在C语言中使用的是格式化输出比如%f,这种格式化输出默认采用的四舍五入策略,导致它看上去似乎是对的!如果你用%.30f你就会发现问题了。

基本减法中的Python错误? [复制]

【中文标题】基本减法中的Python错误? [复制]【英文标题】:Python error in basic subtraction? [duplicate] 【发布时间】:2012-12-16 17:15:42 【问题描述】:

可能重复:Python rounding error with float numberspython maths is wrong

我无法让 Python 正确执行减法 1 - 0.8 并分配它。它不断地给出不正确的答案,0.19999999999999996。

我探索了一下:

sq = 
sub = 
for i in range(1000):
    sq[str(i/1000.)+'**2']=((i/1000.)**2)
    sub['1-'+str(i/1000.)]=(1.0-(i/1000.))

并发现此错误发生在 0 到 1 到小数点后第三位的随机浮点组中。当您对这些浮点数进行平方时,也会发生类似的错误,但对不同的子集。

我希望对此有一个解释,以及如何让 Python 做正确的算术运算。使用round(x,3) 是我目前正在使用的解决方法,但它并不优雅。

谢谢!

这是我的 Python 2.7.3 shell 中的一个会话:

*** Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32. ***
*** Remote Python engine  is active ***
>>> 1-0.8
0.19999999999999996
>>> print 1-0.8
0.2
>>> a = 1-0.8
>>> a
0.19999999999999996
>>> print a
0.2
>>> a = 0.2
>>> print a
0.2
>>> a
0.2
>>> 

这是我放入几个在线解释器的代码:

def doit():
    d = 'a':1-0.8
    return d

print doit()

和输出:

'a': 0.19999999999999996

【问题讨论】:

检查yoda.arachsys.com/csharp/floatingpoint.html effbot.org/pyfaq/… 【参考方案1】:

浮动数字不会像您期望的那样工作。

对于初学者,请阅读floating point guide。长话短说:计算机将浮点数表示为二进制,事实证明,将精确的十进制小数存储为二进制是不可能的(try it for yourself 在纸上查看原因)。出于实际目的,0.19999999999999996 与 0.2“足够接近”。如果您想将其打印为 0.2,则可以执行以下操作:

print "%0.1f" % floating_point_value

所以你看到的不是错误。这是预期的行为。

【讨论】:

谢谢。顺便说一句,doit() 的输出是字典,而不是整数,所以 print "%0.1f" % doit() 在这种情况下不起作用。 你是对的。我已经更新了答案,使其更加明确。 您对在使用 jq 时如何使用这项工作有什么建议吗?我将 jq 用于一个简单的数学函数,它为我提供了这些类似的输出来解决简单的问题。【参考方案2】:

Python 使用“位”存储浮点数,而有些浮点数无法准确表示,无论您有多少位精度。这就是你在这里遇到的问题。这有点像尝试用小数位数有限的十进制完全准确地写1/3

【讨论】:

【参考方案3】:

使用Decimal 专门为此设计的:

>>> from decimal import Decimal, getcontext
>>> Decimal(1) - Decimal(0.8)
Decimal('0.1999999999999999555910790150')
>>> getcontext().prec = 3
>>> Decimal(1) - Decimal(0.8)
Decimal('0.200')
>>> float(Decimal(1) - Decimal(0.8))
0.2

【讨论】:

为什么要输入浮点数?因此,第一个减法与 OP 有相同的问题。改用字符串:Decimal(1) - Decimal('0.8') -> Decimal('0.2')

以上是关于python中的减法有问题的主要内容,如果未能解决你的问题,请参考以下文章

Cupy中的就地减法与广播

python中时间的减法问题

Python 中的运算符

汇编语言中的加减法~~~~~~~~~困扰我很久了。。有高人吗

从 Python 中的图像中减去 RGB 值

js中的一元加法和一元减法