[issue41198] Round built-in function not shows zeros acording significant figures and calculates different numbers of odd and even

2020-07-02 Thread Carlos Neves


New submission from Carlos Neves :

Hi,

I am observing unexpected behavior with round built-in function about (1) 
significant figures in analytical methods and (2) number of odd and even 
numbers obtained by this function.

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

https://en.wikipedia.org/wiki/Significant_figures

1. Significant Figures
==

For example, when I say 1.20 in analytical methods, I am confident about the 
last digit, the zero. It has a meaning. But, when I use Python,

>>> round (1.203, 2)
1.2
>>>

the zero not appears. It is not occur when the second digit is not zero. 

>>> round (1.213, 2)
1.21
>>>

The zero should be printed like the other numbers to be consistent with the 
significant figures. Maybe other functions could present the same behavior.

2. Rounding procedure
=

I wrote the following code to test the number of odd and even numbers during a 
round procedure. I should get half-and-a-half of odd and even numbers. But the 
result using the round function is different. We observed 5 even more and 5 odd 
less. This behavior causes a systematic error.

https://en.wikipedia.org/wiki/Rounding

I hope to be contributing to the improvement of the code.

Thank advanced.


##
# This code count the number of odd and even number with different procedures: 
truncate, round simple and round function 
# Test condition: Rounding with one digit after the decimal point.

import numpy as np

even_0 = 0
odd_0 = 0

even_1 = 0
odd_1 = 0

even_2 = 0
odd_2 = 0

even_3 = 0
odd_3 = 0

# generate 1000 numbers from 0.000 up to 1 with step of 0.001
x = np.arange(0,1,0.001) 

# printing 
for i in range(len(x)): 

x_truncated = int((x[i]*10)+0.0)/10 # no rounding
x_rounded_simple = int((x[i]*10)+0.5)/10 # rounding up at 5
x_rounded_function = round(x[i],1) # rounding by function with one 
digit after the decimal point

# counting odd and even numbers
if int(x[i]*1000) % 2 == 0:
even_0 += 1
else:
odd_0 += 1

if int(x_truncated*10) % 2 == 0:
even_1 += 1
else:
odd_1 += 1

if int(x_rounded_simple*10) % 2 == 0:
even_2 += 1
else:
odd_2 += 1

if int(x_rounded_function*10) % 2 == 0:
even_3 += 1
else:
odd_3 += 1

print ("{0:.3f} {1:.1f} {2:.1f} {3:.1f}".format((x[i]), x_truncated, 
x_rounded_simple, x_rounded_function))

print ("Result:")
print ("Raw: Even={0}, Odd={1}".format(even_0,odd_0))   
print ("Truncated: Even={0}, Odd={1}".format(even_1,odd_1))
print ("Rounded simple: Even={0}, Odd={1}".format(even_2,odd_2))
print ("Rounded Function: Even={0}, Odd={1}".format(even_3,odd_3))

##

Output
...
0.995 0.9 1.0 1.0
0.996 0.9 1.0 1.0
0.997 0.9 1.0 1.0
0.998 0.9 1.0 1.0
0.999 0.9 1.0 1.0
Result:
Raw: Even=500, Odd=500
Truncated: Even=500, Odd=500
Rounded simple: Even=500, Odd=500
Rounded Function: Even=505, Odd=495



--
components: Library (Lib)
messages: 372878
nosy: Carlos Neves, lemburg, mark.dickinson, rhettinger, stutzbach
priority: normal
severity: normal
status: open
title: Round built-in function not shows zeros acording significant figures and 
calculates different numbers of odd and even
type: behavior
versions: Python 3.8

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



[issue41198] Round built-in function not shows zeros acording significant figures and calculates different numbers of odd and even

2020-07-02 Thread Carlos Neves

Carlos Neves  added the comment:

Hi Peters,

I will pay more attention to the Python docs :)
Thank you for your direction.

Carlos A. Neves

Em qui., 2 de jul. de 2020 às 18:22, Tim Peters
 escreveu:
>
>
> Tim Peters  added the comment:
>
> For the first, your hardware's binary floating-point has no concept of 
> significant trailing zeroes. If you need such a thing, use Python's `decimal` 
> module instead, which does support a "significant trailing zero" concept. You 
> would need an entirely new data type to graft such a notion onto Python's (or 
> numpy's!) binary floats.
>
> For the second, we'd have to dig into exactly what numpy's `arange()` does. 
> Very few of the numbers you're working with are exactly representable in 
> binary floating point except for 0.0. For example, "0.001" is approximated by 
> a binary float whose exact decimal value is
>
> 0.00120816681711721685132943093776702880859375
>
> Sometimes the rounded (by machine float arithmetic) multiples of that are 
> exactly representable, but usually not. For example,
>
> >>> 0.001 * 250
> 0.25
>
> rounds to the exactly representable 1/4, and
>
> >>> 0.001 * 750
> 0.75
>
> to the exactly representable 3/4. However, `round()` uses 
> round-to-nearest/even, and then
>
> >>> round(0.25, 1)
> 0.2
> >>> round(0.75, 1)
> 0.8
>
> both resolve the tie to the closest even value (although neither of those 
> _results_ are exactly representable in binary floating-point - although if 
> you go on to multiply them by 10.0, they do round (in hardware) to exactly 
> 2.0 and 8.0).
>
> Note that numpy's arange() docs do warn you against using it ;-)
>
> """
> When using a non-integer step, such as 0.1, the results will often not be 
> consistent. It is better to use numpy.linspace for these cases.
> """
>
> --
> nosy: +tim.peters
>
> ___
> Python tracker 
> <https://bugs.python.org/issue41198>
> ___

--

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