New submission from Wolfgang Maier <wolfgang.ma...@biologie.uni-freiburg.de>:

Hi,

because of floating point inaccuracies it is suboptimal to use round(int1/int2) 
for rounding of a fraction.
fractions.Fraction, OTOH, offers exact rounding through its implementation of 
__round__, but using it requires users to create a fractions.Fraction instance 
from two ints first.
The algorithm used by Fraction.__round__ is, essentially, the same as the one 
used in the pure-Python version of the datetime._divide_and_round module 
(which, in turn, is taken from a comment by Mark Dickinson in 
Objects/longobject.c).

My suggestion is to promote this algorithm to an exposed function in the 
fractions module (actually, it may make sense to have it in the math module 
instead - compare the case of the gcd function, which started out in fractions, 
but is now in transition to math) so that it can be used by Fraction.__round__, 
but also any other code.

Attached is a patch demonstrating the idea. In addition, to the above benefit, 
it turns out to actually speed up Fraction.__round__ substantially, when 
ndigits is not None because it then avoids the generation of temporary Fraction 
instances, and, in my hands at least, it even makes the general (ndigits=None) 
case slightly faster (apparently the copied datetime._divide_and_round code is 
more efficient than the original in Fraction.__round__).

There is one slight additional tweak in the patch: in the case of ndigits < 0, 
it returns an int, not a Fraction (see test_fractions modification to make it 
pass).
I think this is actually a mistake in the current Fraction.__round__, which 
already promotes the result to int in the general case. This change speeds up 
round to the next ndigits power of ten by ~ a factor of 5 in my hands because 
no new Fraction needs to be instantiated anymore.

A full PR could include having pure-Python datetime import the function from 
fractions instead of rolling its own, but I'd first like to hear whether you 
think this should go into math instead.

----------
components: Library (Lib)
files: fractions_divround.patch
keywords: patch
messages: 305817
nosy: mark.dickinson, wolma
priority: normal
severity: normal
status: open
title: make it simpler to round fractions
type: enhancement
versions: Python 3.7, Python 3.8
Added file: https://bugs.python.org/file47254/fractions_divround.patch

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue31978>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to