[issue39059] Getting incorrect results in rounding procedures

2019-12-17 Thread Mark Dickinson


Change by Mark Dickinson :


--
nosy:  -mark.dickinson

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-17 Thread AVicennA


AVicennA  added the comment:

@mark.dickinson:

You asked some questions, then, I also asked you about solving this problem. It 
seems to me you just love to talk.. I just answered to your questions. If "this 
isn't the right forum for that discussion" as you mean, it concerns you too. 
When you ask it's right, but when I answer it's wrong place to discuss ?! I can 
change this line of my post - "In this case, whatever the range the full right 
result is a return" to " In this case, sometimes right result can be return 
like a round". round function also not work properly, my_round too. Each of 
them must be used in its place. In the end I wanna say that, if you want to 
discuss this further,  please, we can continue conversation in mailing list or 
where you want. Thanks.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Kubilay Kocak


Change by Kubilay Kocak :


--
nosy:  -koobs

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Mark Dickinson


Mark Dickinson  added the comment:

@AVicennA: 4.39 *is* the correctly-rounded result for `round(4.395, 2)`. Modulo 
(as-yet unreported) bugs, `round` does correct-rounding (in the IEEE 754 sense) 
in all cases. I was pointing out that your `my_round` does not solve the 
problem you think it does: presumably you'd consider the "correct" result for 
`round(4.395, 2)` to be `4.4`, so you'd like `my_round(4.395, 2)` to return 
`4.4`?

> Do you have any suggestion to solve this problem?

The "problem" presumably being that two-argument `round` gives surprising 
results, to those who haven't thought about the implications of binary 
floating-point?

Unfortunately, there's no easy solution here. Discouraging use of two-argument 
round, and perhaps eventually deprecating it, is one possibility; there are few 
really good use-cases for two-argument round - most of the common use-cases 
involve rounding for reporting purposes, and that's better handled by string 
formatting. Keeping two-argument round and documenting the issue is another, 
and that's the solution the Python core devs have chosen. A more drastic 
solution would be to have Python's numeric literals use decimal floating-point 
by default instead of binary floating-point, so that we finally have a What You 
See Is What You Get behaviour for floating-point. That would be a huge change 
with many implications, and it's definitely way out of scope for this issue.

If you want to discuss this further, please feel free to do so, but not here: 
this isn't the right forum for that discussion.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Steve Dower


Change by Steve Dower :


--
nosy:  -steve.dower

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread AVicennA


AVicennA  added the comment:

@mark.dickinson,

1) Where is your "`round` is giving the correct result in all cases"??

>>> round(4.395, 2)
4.39

2) I wrote it in my post using decimal punct:
''' 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.76468025576890795491635799407958984375
 &&
 2.675 --> 
2.67482236431605997495353221893310546875

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

3) round(2.6748, 2) --> this is the same with round(2.675, 2).

4) I also have a question for you.. Do you have any suggestion to solve this 
problem?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Terry J. Reedy


Terry J. Reedy  added the comment:

The flaw in my_round is that it rounds twice, not once.  The first rounding is 
caused by multiplying by a factor that is not a power of 2.  

In the case of 2.675, that rounding is up enough to affect the second rounding.
>>> format(2.675, ".17f")
'2.67482'
>>> format(2.675 *100, ".17f")
'267.5'

In the case of 4.395, the first rounding is down.
>>> format(4.395, ".17f")
'4.39457'
>>> format(4.395 *100, ".17f")
'439.44316'
Even if it had been up, it might not have been enough to affect the outcome, as 
57 is a lot farther from 100 than 82.

If you want to discuss floating point approximations and rounding further, 
please post to python-list, not here.

--
components:  -Documentation, FreeBSD, IDLE, Library (Lib), Tests, Windows, macOS
versions:  -Python 3.6

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread AVicennA


AVicennA  added the comment:

@steven.daprano, yes, my_round(2.675, 2) --> gave 2.68 and it's not buggy and 
not wrong. This is correct in this case. I advise you look at 5th class math 
book.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Mark Dickinson


Change by Mark Dickinson :


--
resolution:  -> not a bug
stage:  -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Mark Dickinson


Mark Dickinson  added the comment:

@AVicennA: as the docs you linked to explain, this is not a bug: `round` is 
giving the correct result in all cases (or at least, as correct as is possible 
given the use of binary floating-point).

Let's take just the first case, `round(2.675, 2)`. `2.675` is a numeric literal 
in the source that's converted to a Python object of type `float` whose value 
is stored[*] using the IEEE 754 binary64 format. The exact value of that object 
is then 2.67482236431605997495353221893310546875.

So the value that Python sees when rounding is *less* than the halfway case 
2.675, so it rounds down to 2.67. If you think that's not the right thing to 
do, I have a question for you: what result would you expect 
`round(2.6748, 2)` to give?

Your proposed my_round replacement is not a fix: unlike *round*, it does *not* 
do correct rounding in all cases, and does not always give the naively expected 
result in all cases either. To give just one example of many:

>>> my_round(4.395, 2)
4.39

So I don't really understand what action you're proposing here. `round` is as 
good as it can reasonably be, and the documentation already explains the 
weaknesses and links to further reading. Unless you're proposing that Python 
adopt decimal floating-point for its core float type, or that two-argument 
round be deprecated, there not really anything to be done here.

[*] Disclaimer: use of IEEE 754 is not guaranteed, but is overwhelmingly likely 
on common platforms.

--
nosy: +mark.dickinson

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread Steven D'Aprano


Steven D'Aprano  added the comment:

You've spent a lot of time demonstrating behaviour, but have not given us any 
reason why you think the results given are wrong.

As far as I can tell, every single example you show is correct. You have even 
quoted one of the relevant sections from the docs. "This is not a bug..."

You've flagged this is a documentation bug, an IDLE bug, an interpreter core 
bug, a library bug, etc. It isn't all of those things! I don't know what you 
actually want: do you want to improve the documentation? Something else?

By the way, your function "my_round" is buggy. This is wrong:

my_round(2.675, 2)
2.68

The binary float 2.675 is exactly equal to 3011782250804019/1125899906842624, 
or in decimal, exactly 

2.67482236431605997495353221893310546875

Rounding to two decimal places is 2.67, not 2.68.

Can you explain why we shouldn't close this as Not A Bug?

--
nosy: +steven.daprano

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39059] Getting incorrect results in rounding procedures

2019-12-16 Thread AVicennA

New submission from AVicennA :

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.76468025576890795491635799407958984375
 &&
 2.675 --> 
2.67482236431605997495353221893310546875

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

>>> from decimal import Decimal
>>> Decimal(2.675)
Decimal('2.67482236431605997495353221893310546875')
>>>
>>> Decimal(5.765)
Decimal('5.76468025576890795491635799407958984375')

''' 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. '''

--
assignee: docs@python
components: Documentation, FreeBSD, IDLE, Interpreter Core, Library (Lib), 
Tests, Windows, macOS
messages: 358467
nosy: AVicennA, docs@python, koobs, ned.deily, paul.moore, ronaldoussoren, 
steve.dower, terry.reedy, tim.golden, zach.ware
priority: normal
severity: normal
status: open
title: Getting incorrect results in rounding procedures
type: behavior
versions: Python 3.6, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com