Strange behaviour with floats and string conversion

后端 未结 3 1156
忘掉有多难
忘掉有多难 2020-11-27 19:39

I\'ve typed this into python shell:

>>> 0.1*0.1
0.010000000000000002

I expected that 0.1*0.1 is not 0.01, because I know that 0.1

3条回答
  •  [愿得一人]
    2020-11-27 20:25

    The crucial requirement on repr is that it should round-trip; that is, eval(repr(f)) == f should give True in all cases.

    In Python 2.x (before 2.7) repr works by doing a printf with format %.17g and discarding trailing zeroes. This is guaranteed correct (for 64-bit floats) by IEEE-754. Since 2.7 and 3.1, Python uses a more intelligent algorithm that can find shorter representations in some cases where %.17g gives unnecessary non-zero terminal digits or terminal nines. See What's new in 3.1? and issue 1580.

    Even under Python 2.7, repr(0.1 * 0.1) gives "0.010000000000000002". This is because 0.1 * 0.1 == 0.01 is False under IEEE-754 parsing and arithmetic; that is, the nearest 64-bit floating-point value to 0.1, when multiplied by itself, yields a 64-bit floating-point value that is not the nearest 64-bit floating-point value to 0.01:

    >>> 0.1.hex()
    '0x1.999999999999ap-4'
    >>> (0.1 * 0.1).hex()
    '0x1.47ae147ae147cp-7'
    >>> 0.01.hex()
    '0x1.47ae147ae147bp-7'
                     ^ 1 ulp difference
    

    The difference between repr and str (pre-2.7/3.1) is that str formats with 12 decimal places as opposed to 17, which is non-round-trippable but produces more readable results in many cases.

提交回复
热议问题