Python中小数的精度

Rya*_*nce 0 python precision decimal

我不是指精确度,因为小数点后显示的数字是多少.我的意思是精确度,因为我想在这个象形文字功能中使用的十进制数字仍然比它应该是十分之一.我尝试过使用多种不同的策略,包括导入十进制模块.这是我试图使用的功能.

values = [('tens', 10), ('fives', 5), ('ones', 1), ('tenths', 0.1)]

def get_digits(num):
    num = int(num * 10)
    num = float(num) / 10

    output_dict = {}
    for place, value in values:
        output_dict[place] = int(num // value)
        num = num % value

    return output_dict
Run Code Online (Sandbox Code Playgroud)

使用get_digits(277.9),收益率{'tens': 27, 'ones': 2, 'tenths': 8, 'fives': 1}

我需要它说 {'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1}

通过在填充字典后添加1到十分之一来修复它不起作用,因为并非每个小数都不精确地出现.

get_digits(277.6) 回报 {'fives': 1, 'tenths': 6, 'tens': 27, 'ones': 2}

我一直在寻找答案的论坛,但没有得到它.任何帮助将不胜感激.

jed*_*rds 5

正如我试图在评论中解释的那样,问题是你使用的是浮点数.

有关浮点的更多信息,请参见1,2.

问题是实际上277.9并没有存储,而是"非常接近":277.9

print('%.40f' % a)
277.8999999999999772626324556767940521240234
Run Code Online (Sandbox Code Playgroud)

解决方案不是使用一些任意的启发式来判断数学是否稍微偏离并尝试纠正它.我们知道数学略有偏差 - 这是浮点数给我们的礼物和诅咒.

真正的解决方案是使用定点数学,例如,使用Python的decimal模块.


编辑

from decimal import Decimal

values = [
    ('tens',   Decimal(10)),
    ('fives',  Decimal(5)),
    ('ones',   Decimal(1)),
    ('tenths', Decimal('0.1'))
]

def get_digits(num):
    output_dict = {}
    for place, value in values:
        output_dict[place] = int(num // value)  # Cast from Decimal to int
        num = num % value
    return output_dict

num = Decimal('277.9')
print(get_digits(num))
# {'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1}

num = Decimal('277.6')
print(get_digits(num))
#{'tens': 27, 'ones': 2, 'tenths': 6, 'fives': 1}
Run Code Online (Sandbox Code Playgroud)

上面的代码与你的代码非常相似,但是使用了Python的十进制模块.不需要启发式检查.代码正常工作,因为小数字准确表示.