This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author AVicennA
Recipients AVicennA, docs@python, koobs, ned.deily, paul.moore, ronaldoussoren, steve.dower, terry.reedy, tim.golden, zach.ware
Date 2019-12-16.08:50:50
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1576486251.62.0.0931327693234.issue39059@roundup.psfhosted.org>
In-reply-to
Content
This is about rounding process and getting incorrect results. In documentation written
that, "This is not a bug: it’s a result of the fact that most decimal fractions can’t be 
represented exactly as a float". - https://docs.python.org/3/library/functions.html?highlight=round#round
It is also related with hardware. I wrote some code parts that shows it and used decimal value
as in documentation sample:

''' 2.675(4) - (4) or (3) or (2) etc. I have given range 2, and the result is influenced not 
    just by one number after those 2 ranges, but also the another number consistently. '''

>>> round(2.675, 2)
2.67
>>>
>>> round(5.765, 2)
5.76
>>>
>>> round(2.6754, 2)
2.68
>>>
>>> round(5.7652, 2)
5.77

''' "format" is also not working properly. Gives incorrect results. '''

>>> format(2.675, ".2f")  
'2.67'
>>>
>>> format(2.678, ".2f")
'2.68'
>>>
>>> '{:0.2f}'.format(2.675)
'2.67'
>>>
>>> '{:0.2f}'.format(2.678)
'2.68'

''' Because, when the decimal string is converted to a binary floating-point number, it's 
    again replaced with a binary approximation:

    Whose exact value is 5.765 --> 5.76499999999999968025576890795491635799407958984375
                                                 &&
                         2.675 --> 2.67499999999999982236431605997495353221893310546875

    It means that, the 76(5) --> 5 replaced in a memory as 4.(999999999999)
                                                 &&
                       67(5) --> 5 replaced in a memory as 4.(999999999999) '''

>>> from decimal import Decimal
>>> Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')
>>>
>>> Decimal(5.765)
Decimal('5.76499999999999968025576890795491635799407958984375')

''' Used float point precision(FPU) with math lib to apply a certain correct form. 
    I propose to use some tricks. But again incorrect result in third sample: '''

>>> import math
>>> math.ceil(2.675 * 100) / 100
2.68
>>>
>>> print("%.2f" % (math.ceil(2.675 * 100) / 100))
2.68
>>> math.ceil(2.673 * 100) / 100
2.68

''' The most correct form is using by round: '''

>>> round(2.675 * 100) / 100
2.68
>>>
>>> round(2.673 * 100) / 100
2.67
>>> round(2.674 * 100) / 100
2.67
>>> round(2.676 * 100) / 100
2.68

''' In this case, whatever the range the full right result is a return.
    Mostly can be using in fraction side correctness. '''

>>> def my_round(val, n):
...     return round(val * 10 ** n) / 10 ** n
...
>>> my_round(2.675, 2)
2.68
>>>
>>> my_round(2.676, 2)
2.68
>>>
>>> my_round(2.674, 2)
2.67
>>>
>>> my_round(2.673, 2)
2.67
>>>
>>> my_round(2.674, 3)
2.674
>>>
>>> my_round(55.37678, 3)
55.377
>>>
>>> my_round(55.37678, 2)
55.38
>>>
>>> my_round(55.37478, 2)
55.37
>>>
>>> my_round(224.562563, 2)
224.56
>>>
>>> my_round(224.562563, 3)
224.563
>>>
>>> my_round(224.562563, 4)
224.5626
>>>
>>> my_round(224.562563, 5)
224.56256
>>>
>>> my_round(224.562563, 7)
224.562563
>>>
>>> my_round(224.562563, 11)
224.562563

''' my_round - function tested on Windows and Linux platforms(x64). This can be added in Python
    next releases to solve this problem which related with the IEEE 754 and PEP 754 problems. '''
History
Date User Action Args
2019-12-16 08:50:51AVicennAsetrecipients: + AVicennA, terry.reedy, paul.moore, ronaldoussoren, tim.golden, ned.deily, docs@python, zach.ware, koobs, steve.dower
2019-12-16 08:50:51AVicennAsetmessageid: <1576486251.62.0.0931327693234.issue39059@roundup.psfhosted.org>
2019-12-16 08:50:51AVicennAlinkissue39059 messages
2019-12-16 08:50:50AVicennAcreate