【问题标题】:Is there a way to inhibit rounding in python?有没有办法抑制python中的舍入?
【发布时间】:2015-01-23 08:22:44
【问题描述】:

有没有办法抑制 python 舍入,例如:

>>> getcontext().prec = 11; print (Decimal(1.1237836550999999999)*10**10)
11237836551

我需要显示小数点的前 10 位,所以实际上我需要 11237836550 作为输出,我不需要对最后一位进行四舍五入(在本例中,0 舍入为 1)。

有时我可以只增加精度(不是在这种情况下),然后安全地执行计算,如下所示:

>>> getcontext().prec = 14; print (Decimal(1.12378365509978)*10**10)
11237836550.998

但是假设您不知道“0”之后数字的小数部分,例如它可能是 1.1237836550999999999999999999999999... 等等,然后你不能依赖这个“解决方法”。

那么,有没有办法告诉python,“对于这个计算,我不希望进行任何舍入,实际上我希望你只返回所需的小数位数(在本例中为 10),并且在它之后扔掉其他任何东西”?

我在这里查看了Truncating floats in Python,但基本上我需要的不是截断浮点数的字符串,而是另一个用于执行计算的小数。 此外,我链接的帖子中接受的答案的 trunc 函数在这种情况下将不起作用,因为 Decimal 在传递给函数的“f”参数之前将被四舍五入:

>>> def trunc(f, n):
...     '''Truncates/pads a float f to n decimal places without rounding'''
...     return ('%.*f' % (n + 1, f))[:-1]
... 
>>> trunc(Decimal(1.12378365509978), 10)
'1.1237836551' # and not 1.1237836550 as needed

我怎样才能做到这一点?

【问题讨论】:

    标签: python decimal rounding


    【解决方案1】:

    你的问题不是Decimal。这是float。即:

    >>> 1.1237836550999999999
    1.1237836551
    

    但如果你这样做:

    >>> int(Decimal("1.1237836550999999999")*10**10)
    11237836550
    

    你可以走了。以更高的精度初始化小数时使用字符串。

    【讨论】:

    • 好的,谢谢,它是否总是有效,即使我有一个无限 9 的数字?比如 1.1237836550999999999999999999.........?
    • 它似乎不适用于>>> getcontext().prec = 11; print (int(Decimal(1.123783655099999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)*10**10)) 它仍然输出1.1237836551
    • @user3019105 您仍然缺少引号。使用字符串。如果按原样编写,则在传递给 Decimal 构造函数之前将其转换为机器精度浮点数;双精度浮点数大约有 15 个小数位的精度,所以你写下的所有 9 都是无用的。
    • 知道了,谢谢!现在它可以工作了,但是这里的 int() 的目的是什么,即使没有它,它似乎也可以工作:print (Decimal('1.12378365509999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999')*10**10) 输出 11237836550
    • @user3019105 请注意,我在示例中使用了 python shell。如果你想在打印到标准输出的脚本中使用它,你需要print
    【解决方案2】:

    这是你发现的:

    from decimal import *
    
    getcontext().prec = 103
    
    def precision(context, prec=100):
    
        return Decimal(context).quantize(Decimal('.'+'0'*(prec-1)+'1'), rounding=ROUND_DOWN)
    
    print precision(Decimal(10).log10() / Decimal(2).log10())
    

    输出:

    3.3219280948873623478703194294893901758648313930245806120547563958159347766086252158501397433593701550
    

    【讨论】:

    • 这似乎是一个更可靠的解决方案,不是吗?
    • 如何使用 quantize 与变量结果,即表达式的结果,Decimal(math.sqrt(2) + 5).quantize('.00000000001') 给出TypeError: conversion from str to Decimal is not supported
    • @user3019105 里面的quantizeDecimal,别忘了! In[5]: Decimal(math.sqrt(2) + 5).quantize(Decimal('.00000000001'), rounding=ROUND_DOWN) 会给你的输出没有错误Out[5]: Decimal('6.41421356237')
    • 需要指定舍入方式,如答案所示:(Decimal(2).sqrt() + Decimal(5)).quantize(Decimal('.0000000000000000000000000000000000000001'), rounding=ROUND_DOWN)
    • @user3019105 设置getcontext().prec = 200,尝试将prec=100 然后prec=110 与您的表达式放在上面。使用 prec=110 它给你 ...55099...prec=100 它给你 ...550 。所以我认为无论preth 数字后面有多少个数字和什么数字,它都是可靠的
    猜你喜欢
    • 1970-01-01
    • 2010-09-16
    • 2017-02-15
    • 2010-10-28
    • 2013-12-13
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    相关资源
    最近更新 更多