[Python-ideas] Yet another sum function (fractions.sum)

Oscar Benjamin oscar.j.benjamin at gmail.com
Thu Aug 22 13:49:52 CEST 2013


On 22 August 2013 12:11, Chris Angelico <rosuav at gmail.com> wrote:
> On Thu, Aug 22, 2013 at 8:58 PM, Oscar Benjamin
> <oscar.j.benjamin at gmail.com> wrote:
>> If the int is out of range you'll get an error:
>>>>> 1.0 * (10 ** 1000)
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in <module>
>> OverflowError: long int too large to convert to float
>>
>> An implicit float conversion does not quietly lose precision. All
>> subsequent values are usually infected and get turned into floats. The
>> implicit float conversion only happens in two cases:
>> 1) You mixed a float into your otherwise exact integer computation.
>> 2) Division.
>
>>>> (1<<64)*3//2+10
> 27670116110564327434
>>>> (1<<64)*3/2+10
> 2.7670116110564327e+19
>
> It's not so large that it cannot be converted to floating point, but
> it's above the point at which floats are accurate to the integer.
> Therefore precision has been lost. Is it obvious from the second line
> of code that this will be the case? Obviously if you "mix in" a float,
> then it'll infect the calculations. But the effect of the / operator
> is less obvious. Fortunately it's consistent. It will ALWAYS return a
> float. However, I do see this as "implicit" conversion.

As I said you need to be careful around division. There's no right
answer for integer division (for computers). I'd rather have an
implicit conversion than an implicit massively incorrect answer. The
result above has a relative error of ~1e-16. The result below has a
relative error of order 1:

$ py -2.7
>>> 3 / 2
1

If you use that in subsequent calculations your subsequent results
could be *way* off. In many cases where you expected to compute an
integer but end up with a float you'll subsequently get an error:

$ py -3.3
>>> a = [1, 2, 3, 4, 5]
>>> b = 3
>>> a[b / 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not float

If you just get an incorrect integer there's no way to know if it's
exact or not without checking after every division e.g.:

a = b / 2
assert 2 * a == b

which is tedious.


Oscar


More information about the Python-ideas mailing list