确定浮点数的精确小数位数

时间:2016-09-04 12:21:02

标签: python floating-point precision significant-digits

在我的现实问题中,我将窗口小部件的大小乘以size_hint,其中0.可以是1.0。假设窗口小部件的最小大小为10,000且最大大小为size * size_hint,那么当我乘以0.1时,我应该在哪个数字上发生错误?

例如* >>> from decimal import Decimal >>> Decimal.from_float(.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') # ^ # |_ here 上的错误发生在..

>>> 1001*.2
200.20000000000002

..十八进制数字。

另一方面,下面的错误发生在第14个十进制

size

问题

  • 有没有办法确定错误发生在哪个十进制数字上?
  • Python 2和Python 3之间有区别吗?

使用小数而不是浮点数不是一个选项,用户可以提供size_hint>>> 0.1

* 我使用Fraction,因为0.1在控制台中显示为.. example.mp3,但我认为这与它的打印方式有关,而不是它是如何存储的。

3 个答案:

答案 0 :(得分:2)

如果我们假设小部件的大小准确存储,那么有2个错误来源:size_hint从小数转换 - >二进制,和乘法。在Python中,这些都应该正确舍入到最近,因此每个应该具有半个ulp(unit in the last place)的相对误差。由于第二个操作是乘法,我们可以添加边界以获得总相对误差,该误差将是1 ulp或2 -53

转换为十进制:

>>> math.trunc(math.log10(2.0**-53))
-15

这意味着你应该准确到15位有效数字。

Python 2和3之间不应该有任何区别:Python长期以来对浮点行为一直相当严格,我唯一知道的变化就是round函数的行为,这里没有使用。

答案 1 :(得分:2)

回答问题的小数到双精度浮点转换部分...

小数分数在0.0和0.1之间的转换对15-16 decimal digits有好处(注意:你在点之后的第一个非零数字开始计数。)

0.1 = 0.1000000000000000055511151231257827021181583404541015625最好为16位数(舍入为17,为0.10000000000000001;舍入为16,为0.1)。

0.2 = 0.200000000000000011102230246251565404236316680908203125也适合16位数。

(仅限15位数字的例子:

0.81 = 0.810000000000000053290705182007513940334320068359375)

答案 2 :(得分:0)

我建议您阅读pep485

使用==运算符来比较浮点值不是正确的方法,而是考虑使用math.isclosecmath.isclose,这是使用您的值的一个小例子:

try:
    from math import isclose

    v1 = 101 * 1 / 5
    v2 = 101 * (1 / 5)
except:
    v1 = float(101) * float(1) / float(5)
    v2 = float(101) * (float(1) / float(5))

    def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
        return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

print("v1==v2 {0}".format(v1 == v2))
print("isclose(v1,v2) {0}".format(isclose(v1, v2)))

正如你所看到的,我明确地在 python 2.x 中投射并使用文档中提供的函数,使用 python 3.x 我只是直接使用数值模块中的值和提供的函数。