在我的现实问题中,我将窗口小部件的大小乘以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
问题:
使用小数而不是浮点数不是一个选项,用户可以提供size_hint
和>>> 0.1
。
* 我使用Fraction
,因为0.1
在控制台中显示为.. example.mp3
,但我认为这与它的打印方式有关,而不是它是如何存储的。 子>
答案 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.isclose或cmath.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 我只是直接使用数值模块中的值和提供的函数。