numpy - Python (strangely) rounding values -
this question has answer here:
- python float - str - float weirdness 4 answers
this question more curiosity.
i'm creating following array:
a = zeros((2,2)) in range(2): a[i,i] = 0.6 a[(i+1)%2,i] = 0.4 print >>> [[ 0.6 0.4] [ 0.4 0.6]]
then, printing it:
for i,c in enumerate(a): j,d in enumerate(c): print j, d
but, if remove j, got:
>>> 0 0.6 1 0.4 0 0.4 1 0.6
but if remove j for, got:
(0, 0.59999999999999998) (1, 0.40000000000000002) (0, 0.40000000000000002) (1, 0.59999999999999998)
it because way i'm creating matrix, using 0.6? how represent internally real values?
there few different things going on here.
first, python has 2 mechanisms turning object string, called repr
, str
. repr
supposed give 'faithful' output (ideally) make easy recreate object, while str
aims more human-readable output. floats in python versions , including python 3.1, repr
gives enough digits determine value of float (so evaluating returned string gives float), while str
rounds 12 decimal places; has effect of hiding inaccuracies, means 2 distinct floats close can end same str
value - can't happen repr
. when print object, str
of object. in contrast, when evaluate expression @ interpreter prompt, 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 # interpreter read-eval-print loop uses 'repr' 0.14285714285714285
but also, little bit confusingly point of view, get:
>>> x = 0.4 >>> str(x) '0.4' >>> repr(x) '0.4'
that doesn't seem tie in seeing above, we'll come below.
the second thing bear in mind in first example, you're printing 2 separate items, while in second example (with j
removed), you're printing single item: tuple of length 2. surprisingly, when converting tuple printing str
, python nevertheless uses repr
compute string representation of elements of tuple:
>>> x = 1.0 / 7.0 >>> print x, x # print x twice; uses str(x) 0.142857142857 0.142857142857 >>> print(x, x) # print single tuple; uses repr(x) (0.14285714285714285, 0.14285714285714285)
that explains why you're seeing different results in 2 cases, though underlying floats same.
but there's 1 last piece puzzle. in python >= 2.7, saw above particular float 0.4
, str
, repr
of float same. 0.40000000000000002
come from? well, don't have python floats here: because you're getting these values numpy array, they're of type numpy.float64
:
>>> numpy import zeros >>> = zeros((2, 2)) >>> a[:] = [[0.6, 0.4], [0.4, 0.6]] >>> array([[ 0.6, 0.4], [ 0.4, 0.6]]) >>> type(a[0, 0]) <type 'numpy.float64'>
that type still stores double-precision float, python's float, it's got goodies make interact nicely rest of numpy. , turns out numpy uses different algorithm computing repr
of numpy.float64
python uses computing repr
of float
. python (in versions >= 2.7) aims give shortest string still gives accurate representation of float, while numpy outputs string based on rounding underlying value 17 significant digits. going 0.4
example above, here's numpy does:
>>> 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 3 things should explain results you're seeing. rest assured cosmetic: underlying floating-point value not being changed in way; it's being displayed differently 4 different possible combinations of str
, repr
2 types: float
, numpy.float64
.
the python tutorial give more details of how python floats stored , displayed, of potential pitfalls. answers this question have more information on difference between str
, repr
.
Comments
Post a Comment