我正在编写一个从数字中提取小数的函数。忽略异常及其语法,我正在研究2.5.2(默认的Leopard版本)。我的功能尚未处理0。我的问题是,该函数产生具有某些数字的随机错误,我不明白其中的原因。我将在代码后发布一个错误读数。
功能:
def extractDecimals(num):
try:
if(num > int(num)):
decimals = num - int(num)
while(decimals > int(decimals)):
print 'decimal: ' + str(decimals)
print 'int: ' + str(int(decimals))
decimals *= 10
decimals = int(decimals)
return decimals
else:
raise DecimalError(num)
except DecimalError, e:
e.printErrorMessage()
异常类:
class DecimalError(Exception):
def __init__(self, value):
self.value = value
def printErrorMessage(self):
print 'The number, ' + str(self.value) + ', is not a decimal.'
输入数字1.988时输出错误:
decimal: 0.988
int: 0
decimal: 9.88
int: 9
decimal: 98.8
int: 98
decimal: 988.0
int: 987
decimal: 9880.0
int: 9879
decimal: 98800.0
int: 98799
decimal: 988000.0
int: 987999
decimal: 9880000.0
int: 9879999
decimal: 98800000.0
int: 98799999
decimal: 988000000.0
int: 987999999
decimal: 9880000000.0
int: 9879999999
decimal: 98800000000.0
int: 98799999999
decimal: 988000000000.0
int: 987999999999
decimal: 9.88e+12
int: 9879999999999
decimal: 9.88e+13
int: 98799999999999
decimal: 9.88e+14
int: 987999999999999
9879999999999998
我不知道为什么会出现这个错误。希望你们能帮助我。
答案 0 :(得分:5)
问题是(二进制)浮点数不能精确表示为小数。有关详细信息,请参阅Why can't decimal numbers be represented exactly in binary?。
答案 1 :(得分:1)
正如Ned Batchelder所说,并非所有小数都可以像浮点数那样完全表示。浮点数由一定数量的二进制数字表示,用于尽可能接近小数。你永远不能假设浮点数完全等于小数。
In [49]: num
Out[49]: 1.988
In [50]: decimals=num - int(num)
In [51]: decimals
Out[51]: 0.98799999999999999
In [52]: print decimals # Notice that print rounds the result, masking the inaccuracy.
0.988
有关浮点数二进制表示的更多信息,请参阅http://en.wikipedia.org/wiki/Floating_point。
还有其他方法可以实现目标。这是一种方法,使用字符串操作:
def extractDecimals(num):
try:
numstr=str(num)
return int(numstr[numstr.find('.')+1:])
except ValueError, e:
print 'The number, %s is not a decimal.'%num
答案 2 :(得分:1)
正如其他人已经指出的那样,你看到的问题是浮点数的不精确表示
使用Python的Decimal
from decimal import Decimal
extractDecimals(Decimal("0.988"))
答案 3 :(得分:1)
正如已经说过的,浮点数不完全等于小数。您可以通过使用模数运算符来看到这一点:
>>> 0.988 % 1
0.98799999999999999
>>> 9.88 % 1
0.88000000000000078
>>> 98.8 % 1
0.79999999999999716
这给出除数的余数1或小数。
答案 4 :(得分:0)
正如其他人在他们的回答中所说的那样,使用浮点数的算法并不总是会因为舍入错误而导致您的期望。在这种情况下,也许将浮点数转换为字符串并返回更好?
In [1]: num = 1.988
In [2]: num_str = str(num)
In [3]: decimal = num_str.split('.')[1]
In [4]: decimal = int(decimal)
In [5]: decimal
Out[5]: 988