Message358467
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. ''' |
|
Date |
User |
Action |
Args |
2019-12-16 08:50:51 | AVicennA | set | recipients:
+ AVicennA, terry.reedy, paul.moore, ronaldoussoren, tim.golden, ned.deily, docs@python, zach.ware, koobs, steve.dower |
2019-12-16 08:50:51 | AVicennA | set | messageid: <1576486251.62.0.0931327693234.issue39059@roundup.psfhosted.org> |
2019-12-16 08:50:51 | AVicennA | link | issue39059 messages |
2019-12-16 08:50:50 | AVicennA | create | |
|