将numpy.float64转换为float时的奇怪行为

时间:2022-09-27 04:05:26

I'm having the strangest behavior with an object generated by numpy.arange:

我对numpy.arange生成的对象有最奇怪的行为:

for i in numpy.arange(xo, xn+h, h):
    xs.append(float(i))

In this case, xo=1, xn=4, h=0.1.

在这种情况下,xo = 1,xn = 4,h = 0.1。

Now, I expected xs[-1] to be exactly equal to 4.0 == float(4). However, I get the following:

现在,我预计xs [-1]将完全等于4.0 == float(4)。但是,我得到以下内容:

>>> foo = xs[-1]
>>> foo == float(4)
False
>>> float(foo) == float(4)
False
>>> foo
4.0
>>> type(foo)
<type 'float'>
>>> int(sympy.ceiling(4.0)), int(sympy.ceiling(foo))
4 5

What on earth is happening here?

这到底发生了什么?

Placing print type(i) in the for loop prints <type 'numpy.float64'>. Perhaps something going on during the float(i) casting? Using numpy.asscalar doesn't change anything.

将打印类型(i)放在for循环中打印 。在浮动(i)投射期间可能会发生什么?使用numpy.asscalar不会改变任何东西。 'numpy.float64'>

Using math.ceil(foo) instead of sympy.ceiling(foo) issues the same thing (that's the part I actually need to work).

使用math.ceil(foo)而不是sympy.ceiling(foo)发出同样的事情(这是我实际需要工作的部分)。

2 个解决方案

#1


2  

In [10]: for i in numpy.arange(xo, xn+h, h):
        xs.append(float(i))
....:     

In [11]: xs
Out[11]: 
[1.0,
1.1,
1.2000000000000002,
1.3000000000000003,
1.4000000000000004,
1.5000000000000004,
1.6000000000000005,
1.7000000000000006,
1.8000000000000007,
1.9000000000000008,
2.000000000000001,
2.100000000000001,
2.200000000000001,
2.300000000000001,
2.4000000000000012,
2.5000000000000013,
2.6000000000000014,
2.7000000000000015,
2.8000000000000016,
2.9000000000000017,
3.0000000000000018,
3.100000000000002,
3.200000000000002,
3.300000000000002,
3.400000000000002,
3.500000000000002,
3.6000000000000023,
3.7000000000000024,
3.8000000000000025,
3.9000000000000026,
4.000000000000003]

This is why you do not get the wanted result, due to floating point accuracy, it cant give True to your test. This also explains why if you do a round-operation like ceiling on it, that you get five instead of four.

这就是为什么你没有得到想要的结果,由于浮点精度,它不能给你的测试真实。这也解释了为什么如果你做一个像天花板这样的圆形操作,那你得到五个而不是四个。

edit: to check if x and y are the same (within some margin of error), you could do the following, but i think there is (should be) something already in python that can do this for you

编辑:检查x和y是否相同(在某个误差范围内),您可以执行以下操作,但我认为(应该)已经在python中可以为您执行此操作

def isnear(x,y, precision = 1e-5):
    return abs(x-y)<precision

edit2: or as ali_m said:

edit2:或者作为ali_m说:

numpy.allclose(x, y, atol = 1e-5)

#2


1  

This is not really strange - it is just the way that floating point arithmetic works because it cannot represent most values exactly. If you do repeated computations in floating point (arange() here is adding 0.1 to 1 and then adding 0.1 to that sum another 29 times) and if the numbers you are dealing with are not exactly representable in floating point, you won't get an exact answer at the end of the computation. The best article to read on this is What Every Computer Scientist Should Know About Floating-Point Arithmetic.

这并不奇怪 - 它只是浮点运算的工作方式,因为它无法准确表示大多数值。如果你在浮点上重复计算(arange()这里加0.1到1然后再加上0.1加上另外29次)如果你要处理的数字在浮点数上不能完全表示,你就不会得到计算结束时的确切答案。关于这一点的最佳文章是每个计算机科学家应该知道的关于浮点运算的内容。

#1


2  

In [10]: for i in numpy.arange(xo, xn+h, h):
        xs.append(float(i))
....:     

In [11]: xs
Out[11]: 
[1.0,
1.1,
1.2000000000000002,
1.3000000000000003,
1.4000000000000004,
1.5000000000000004,
1.6000000000000005,
1.7000000000000006,
1.8000000000000007,
1.9000000000000008,
2.000000000000001,
2.100000000000001,
2.200000000000001,
2.300000000000001,
2.4000000000000012,
2.5000000000000013,
2.6000000000000014,
2.7000000000000015,
2.8000000000000016,
2.9000000000000017,
3.0000000000000018,
3.100000000000002,
3.200000000000002,
3.300000000000002,
3.400000000000002,
3.500000000000002,
3.6000000000000023,
3.7000000000000024,
3.8000000000000025,
3.9000000000000026,
4.000000000000003]

This is why you do not get the wanted result, due to floating point accuracy, it cant give True to your test. This also explains why if you do a round-operation like ceiling on it, that you get five instead of four.

这就是为什么你没有得到想要的结果,由于浮点精度,它不能给你的测试真实。这也解释了为什么如果你做一个像天花板这样的圆形操作,那你得到五个而不是四个。

edit: to check if x and y are the same (within some margin of error), you could do the following, but i think there is (should be) something already in python that can do this for you

编辑:检查x和y是否相同(在某个误差范围内),您可以执行以下操作,但我认为(应该)已经在python中可以为您执行此操作

def isnear(x,y, precision = 1e-5):
    return abs(x-y)<precision

edit2: or as ali_m said:

edit2:或者作为ali_m说:

numpy.allclose(x, y, atol = 1e-5)

#2


1  

This is not really strange - it is just the way that floating point arithmetic works because it cannot represent most values exactly. If you do repeated computations in floating point (arange() here is adding 0.1 to 1 and then adding 0.1 to that sum another 29 times) and if the numbers you are dealing with are not exactly representable in floating point, you won't get an exact answer at the end of the computation. The best article to read on this is What Every Computer Scientist Should Know About Floating-Point Arithmetic.

这并不奇怪 - 它只是浮点运算的工作方式,因为它无法准确表示大多数值。如果你在浮点上重复计算(arange()这里加0.1到1然后再加上0.1加上另外29次)如果你要处理的数字在浮点数上不能完全表示,你就不会得到计算结束时的确切答案。关于这一点的最佳文章是每个计算机科学家应该知道的关于浮点运算的内容。