Python(奇怪)四舍五入的值 [英] Python (strangely) rounding values

查看:171
本文介绍了Python(奇怪)四舍五入的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我创建了以下数组:

 A [i,i] = 0.6 
A [(i + 1) 1)%2,i] = 0.4
print A

>>>
[[0.6 0.4]
[0.4 0.6]]

(c):

 对于i,c在枚举(A)中:
对于j,d在枚举(c)中:
print j,d

但是,如果我删除了j, p>

 >>> 
0 0.6
1 0.4
0 0.4
1 0.6



但是,如果我从中删除了j,我得到了:

$ p $ (0,0.59999999999999998)
1,0.40000000000000002)
(0,0.40000000000000002)
(1,0.59999999999999998)

因为我创建矩阵的方式,使用0.6?它是如何表示内部实际价值的?

解决方案

这里有几个不同的事情。 b

首先,Python有两个把对象转换成一个字符串的机制,叫做 repr str 。 (code> repr )应该给出'忠实'的输出,这将使(理想情况下)很容易重新创建那个对象,而 str repr 给出了足够的数字以完全确定浮点数(这样计算返回的字符串就可以精确地返回浮点数) ,而 str 轮到12位小数;这有隐藏不准确的效果,但是意味着两个非常接近的浮动元素可能会以相同的 str 值 - 这是<$ code>再版。当你打印一个对象时,你得到该对象的 str 。相比之下,当你只是在解释器提示下评估一个表达式时,你会得到 repr



这里使用Python 2.7):

 >>> x = 1.0 / 7.0 
>>> str(x)
'0.142857142857'
>>> repr(x)
'0.14285714285714285'
>>> print x#print uses'str'
0.142857142857
>>> x#解释器read-eval-print循环使用'repr'
0.14285714285714285

,从你的观点来看有一点点混淆,我们得到:

 >>> x = 0.4 
>>> str(x)
'0.4'
>>> repr(x)
'0.4'

这似乎不太好与你在上面看到,但我们会回到这下面。



第二个要记住的是,在你的第一个例子,你打印两个单独的项目,而在你的第二个例子中( j 删除),你打印一个单一的项目:长度为2的元组。有点令人惊讶的是,对于使用 str 进行打印,Python仍然使用 repr 来计算元素的字符串表示形式

 >>> x = 1.0 / 7.0 
>>>打印x,x#打印x两次;使用str(x)
0.142857142857 0.142857142857
>>> print(x,x)#打印一个元组;使用repr(x)
(0.14285714285714285,0.114285714285714285)

这就解释了为什么你会看到这两种情况下的结果是不同的,即使底层的花车是相同的。



但是最后一块是这个难题。在Python> = 2.7中,我们在上面看到,对于特定的浮动 0.4 str 浮动的repr 是一样的。那么 0.40000000000000002 从哪里来呢?那么这里没有Python浮点数:因为你从NumPy数组中获得这些值,它们实际上是类型 numpy.float64

 >>>从numpy导入零
>>> A =零((2,2))
>>> A [:] = [[0.6,0.4],[0.4,0.6]]
>>> A
数组([[0.6,0.4],
[0.4,0.6]])
>>>类型(A [0,0])

这个类型仍然存储一个双精度浮点数,就像Python的浮点数一样,但是它还有一些额外的好东西这使得它与其余的NumPy很好地相互作用。事实证明,NumPy使用一种稍微不同的算法来计算 numpy.float64 repr 计算 float repr 。 Python(在版本> = 2.7)的目的是给最短的字符串,仍然给出了一个精确的浮点数表示,而NumPy只是输出一个字符串的基础上四舍五入17位有效数字。回到上面的例子 0.4 ,这里是NumPy的功能:

  >>> from numpy import float64 
>>> x = float64(1.0 / 7.0)
>>> str(x)
'0.142857142857'
>>> repr(x)
'0.14285714285714285'
>>> x = float64(0.4)
>>> str(x)
'0.4'
>>> repr(x)
'0.40000000000000002'

看到了。请放心,这完全是一种表达:底层的浮点值没有任何改变;它只是以 str repr 这四种不同的可能组合的方式显示,对于两种类型: float numpy.float64



Python教程给出> 这个SO问题的答案有更多关于 str repr


This question is more for curiosity.

I'm creating the following array:

A = zeros((2,2))
for i in range(2):
    A[i,i] = 0.6
    A[(i+1)%2,i] = 0.4
print A

>>>
   [[ 0.6  0.4]
   [ 0.4  0.6]]

Then, printing it:

for i,c in enumerate(A):
    for j,d in enumerate(c):
        print j, d

But, if I remove the j, I got:

>>>
0 0.6
1 0.4
0 0.4
1 0.6

But if I remove the j from the for, I got:

(0, 0.59999999999999998)
(1, 0.40000000000000002)
(0, 0.40000000000000002)
(1, 0.59999999999999998)

It because the way I'm creating the matrix, using 0.6? How does it represent internally real values?

解决方案

There are a few different things going on here.

First, Python has two mechanisms for turning an object into a string, called repr and str. repr is supposed to give 'faithful' output that would (ideally) make it easy to recreate exactly that object, while str aims for more human-readable output. For floats in Python versions up to and including Python 3.1, repr gives enough digits to determine the value of the float completely (so that evaluating the returned string gives back exactly that float), while str rounds to 12 decimal places; this has the effect of hiding inaccuracies, but means that two distinct floats that are very close together can end up with the same str value - something that can't happen with repr. When you print an object, you get the str of that object. In contrast, when you just evaluate an expression at the interpreter prompt, you get the repr.

For example (here using Python 2.7):

>>> x = 1.0 / 7.0
>>> str(x)
'0.142857142857'
>>> repr(x)
'0.14285714285714285'
>>> print x  # print uses 'str'
0.142857142857
>>> x  # the interpreter read-eval-print loop uses 'repr'
0.14285714285714285

But also, a little bit confusingly from your point of view, we get:

>>> x = 0.4
>>> str(x)
'0.4'
>>> repr(x)
'0.4'

That doesn't seem to tie in too well with what you were seeing above, but we'll come back to this below.

The second thing to bear in mind is that in your first example, you're printing two separate items, while in your second example (with the j removed), you're printing a single item: a tuple of length 2. Somewhat surprisingly, when converting a tuple for printing with str, Python nevertheless uses repr to compute the string representation of the elements of that tuple:

>>> x = 1.0 / 7.0
>>> print x, x  # print x twice;  uses str(x)
0.142857142857 0.142857142857
>>> print(x, x)  # print a single tuple; uses repr(x)
(0.14285714285714285, 0.14285714285714285)

That explains why you're seeing different results in the two cases, even though the underlying floats are the same.

But there's one last piece to the puzzle. In Python >= 2.7, we saw above that for the particular float 0.4, the str and repr of that float were the same. So where does the 0.40000000000000002 come from? Well, you don't have Python floats here: because you're getting these values from a NumPy array, they're actually of type numpy.float64:

>>> from numpy import zeros
>>> A = zeros((2, 2))
>>> A[:] = [[0.6, 0.4], [0.4, 0.6]]
>>> A
array([[ 0.6,  0.4],
       [ 0.4,  0.6]])
>>> type(A[0, 0])
<type 'numpy.float64'>

That type still stores a double-precision float, just like Python's float, but it's got some extra goodies that make it interact nicely with the rest of NumPy. And it turns out that NumPy uses a slightly different algorithm for computing the repr of a numpy.float64 than Python uses for computing the repr of a float. Python (in versions >= 2.7) aims to give the shortest string that still gives an accurate representation of the float, while NumPy simply outputs a string based on rounding the underlying value to 17 significant digits. Going back to that 0.4 example above, here's what NumPy does:

>>> from numpy import float64
>>> x = float64(1.0 / 7.0)
>>> str(x)
'0.142857142857'
>>> repr(x)
'0.14285714285714285'
>>> x = float64(0.4)
>>> str(x)
'0.4'
>>> repr(x)
'0.40000000000000002'

So these three things together should explain the results you're seeing. Rest assured that this is all completely cosmetic: the underlying floating-point value is not being changed in any way; it's just being displayed differently by the four different possible combinations of str and repr for the two types: float and numpy.float64.

The Python tutorial give more details of how Python floats are stored and displayed, together with some of the potential pitfalls. The answers to this SO question have more information on the difference between str and repr.

这篇关于Python(奇怪)四舍五入的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆