【问题标题】:Python increment float by smallest step possible predetermined by its number of decimalsPython按其小数位数预先确定的最小步长递增浮点数
【发布时间】:2018-05-30 15:40:48
【问题描述】:

我已经搜索了几个小时,但找不到完成以下任务的简单方法。

Value 1 = 0.00531
Value 2 = 0.051959
Value 3 = 0.0067123

我想将每个值增加其最小的小数点(但是,该数字必须保持与它开始时的精确小数点数,并且小数点数随每个值而变化,因此我的麻烦)。

Value 1 should be: 0.00532
Value 2 should be: 0.051960
Value 3 should be: 0.0067124

有谁知道在仍然可以处理任意小数的函数中完成上述操作的简单方法?

谢谢。

【问题讨论】:

  • 浮点不是在内部以十进制表示,而是以二进制表示。因此,0.1 例如 not 是可表示的浮点数。它近似于0.099999...ish 或0.1000...ish。所以它会非常不稳定。
  • 如果你真的想要这个,那么你应该切换到非浮点表示(例如,一个整数和一个给出小数位数的数字)。
  • @TomKarzes 的方法有效,但请注意,仅仅因为您看到的十进制表示是 0.00532,实际上可能有 更多 个十进制数字而不是您看到的,所以您可能如果您没有看到整个表示,则会得到与预期不同的结果。
  • .1 + .2 == 0.30000000000000004。这里“真实”的最后一位数字是什么?

标签: python increment


【解决方案1】:

你看过标准模块decimal吗?

它规避了浮点行为。

只是为了说明可以做什么。

import decimal
my_number = '0.00531'
mnd = decimal.Decimal(my_number)
print(mnd)
mnt = mnd.as_tuple()
print(mnt)
mnt_digit_new = mnt.digits[:-1] + (mnt.digits[-1]+1,)
dec_incr = decimal.DecimalTuple(mnt.sign, mnt_digit_new, mnt.exponent)
print(dec_incr)
incremented = decimal.Decimal(dec_incr)
print(incremented)

打印

0.00531
DecimalTuple(sign=0, digits=(5, 3, 1), exponent=-5)
DecimalTuple(sign=0, digits=(5, 3, 2), exponent=-5)
0.00532

或完整版(编辑后还带有任何数字,因此它也适用于'0.199')...

from decimal import Decimal, getcontext

def add_one_at_last_digit(input_string):
    dec = Decimal(input_string)
    getcontext().prec = len(dec.as_tuple().digits)
    return dec.next_plus()

for i in ('0.00531', '0.051959', '0.0067123', '1', '0.05199'):
    print(add_one_at_last_digit(i))

打印出来的

0.00532
0.051960
0.0067124
2
0.05200

【讨论】:

    【解决方案2】:

    正如其他评论者所指出的:您不应该使用floats 进行操作,因为给定的数字0.1234 已转换为内部表示,您无法按照您想要的方式进一步处理它。这是故意含糊其辞的。浮点数本身就是一个主题。 This article 很好地解释了这个主题,是一个很好的主题入门。

    也就是说,您可以做的是将输入作为字符串(例如,从输入读取时不要将其转换为浮点数)。然后你可以这样做:

    from decimal import Decimal
    
    def add_one(v):
        after_comma = Decimal(v).as_tuple()[-1]*-1
        add = Decimal(1) / Decimal(10**after_comma)
        return Decimal(v) + add
    
    if __name__ == '__main__':
        print(add_one("0.00531"))
        print(add_one("0.051959"))
        print(add_one("0.0067123"))
        print(add_one("1"))
    

    打印出来

    0.00532
    0.051960
    0.0067124
    2
    

    更新

    如果您需要对浮动进行操作,您可以尝试使用模糊逻辑来结束演示。 decimal 提供了一个 normalize 函数,可让您降低十进制表示的精度,使其与原始数字匹配:

    from decimal import Decimal, Context
    
    def add_one_float(v):
        v_normalized = Decimal(v).normalize(Context(prec=16))
        after_comma = v_normalized.as_tuple()[-1]*-1
        add = Decimal(1) / Decimal(10**after_comma)
        return Decimal(v_normalized) + add
    

    但请注意16 的精度纯粹是实验性的,您需要使用它来查看它是否会产生预期的结果。如果你需要正确的结果,你不能走这条路。

    【讨论】:

    • @dAJVqgVFsB 谢谢。那你可以投票和/或接受我的回答吗? (这是stackoverflow上的货币..)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    相关资源
    最近更新 更多