Issue 30453: str.format() method, Rounding off wrong (original) (raw)

Created on 2017-05-24 09:45 by kudoshunsaku, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (5)

msg294340 - (view)

Author: Kazuhiro Fujie (kudoshunsaku)

Date: 2017-05-24 09:45

To whom it may concern:

I post issue at first time. Please forgive me if this is rude

C:\Users\kudo-shunsaku>python Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information.

num = 4.625 "{:.2f}".format(num) '4.62' num = 4.645 "{:.2f}".format(num) '4.64' num = 4.655 "{:.2f}".format(num) '4.66'

Please, check this out. I checked it version 3.5.3 and 3.6.1 on Windows and Cent OS.

msg294341 - (view)

Author: Mark Dickinson (mark.dickinson) * (Python committer)

Date: 2017-05-24 09:56

The code is behaving correctly. The surprise is due to the internal binary representation of Python floats, and is related to the documentation note about round here:

https://docs.python.org/3/library/functions.html#round

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.

msg294342 - (view)

Author: Mark Dickinson (mark.dickinson) * (Python committer)

Date: 2017-05-24 10:03

Actually, there are two potential sources of confusion here:

  1. Python uses the round-ties-to-even rounding mode, which means cases that are exactly halfway between two target values round to the value with even last digit. This rule is being used in your first example (4.625), which is a value that's exactly representable in the IEEE 754 binary64 format that Python typically uses to represent floats, and is exactly halfway between 4.2 and 4.3.

  2. It might look as though round-ties-to-even applies in the second and third cases, too, but that's not the case, since these values aren't exactly halfway between the relevant decimal values, thanks to the representation error incurred when translating to the binary64 format. The value specified by the literal "4.645" is stored internally as "4.644999999999999573674358543939888477325439453125", which is a tiny amount closer to 4.64 than to 4.65, so it rounds to 4.64. The value 4.655 works similarly.

msg294343 - (view)

Author: Mark Dickinson (mark.dickinson) * (Python committer)

Date: 2017-05-24 10:12

is exactly halfway between 4.2 and 4.3.

That should have said "between 4.62 and 4.63", of course. Apologies.

msg294449 - (view)

Author: Kazuhiro Fujie (kudoshunsaku)

Date: 2017-05-25 09:08

Hi, Mark

Thank you for teaching politely.

I had misunderstood about format() and round() functions. I made mistakes though I already knew about floating point. I think try to take this tactics on my codes.

num1 = 4.625 num2 = 4.62501 num3 = 4.62500000000001 num4 = 4.625000000000001 num5 = 4.6250000000000001 print(num1, num2, num3, num4, num5) #=> 4.625 4.62501 4.62500000000001 4.625000000000001 4.625

print("{0:.2f} : {1:.2f} : {2:.2f} : {3:.2f} : {4:.2f}".format(num1, num2, num3, num4, num5)) #=> 4.62 : 4.63 : 4.63 : 4.63 : 4.62

print("{0:.3f} : {1:.3f} : {2:.3f} : {3:.3f} : {4:.3f}".format(num1, num2, num3, num4, num5)) #=> 4.625 : 4.625 : 4.625 : 4.625 : 4.625

print("{0:.4f} : {1:.4f} : {2:.4f} : {3:.4f} : {4:.4f}".format(num1, num2, num3, num4, num5)) #=> 4.6250 : 4.6250 : 4.6250 : 4.6250 : 4.6250

print("{0:.16f} : {1:.16f} : {2:.16f} : {3:.16f} : {4:.16f}".format(num1, num2, num3, num4, num5)) #=> 4.6250000000000000 : 4.6250099999999996 : 4.6250000000000098 : 4.6250000000000009 : 4.6250000000000000 data = 4.625 plus = 0.000000000000001 num = data + plus print("{0:.2f}".format(num)) #=> 4.63

Thank you very much.

History

Date

User

Action

Args

2022-04-11 14:58:46

admin

set

github: 74638

2017-05-25 09:08:27

kudoshunsaku

set

messages: +

2017-05-24 10:12:57

mark.dickinson

set

messages: +

2017-05-24 10:03:29

mark.dickinson

set

messages: +

2017-05-24 09:56:18

mark.dickinson

set

status: open -> closed

nosy: + mark.dickinson
messages: +

resolution: not a bug
stage: resolved

2017-05-24 09:45:38

kudoshunsaku

create