[Tutor] Removing duplicates

Oscar Benjamin oscar.j.benjamin at gmail.com
Thu Aug 2 13:54:57 EDT 2018


On 2 August 2018 at 13:49, Peter Otten <__peter__ at web.de> wrote:
> Oscar Benjamin wrote:
>>
>> Comparing floats for equality can be flakey. Sometimes two floats that
>> should be equal will not compare equal e.g.:
>>
>>>>> 0.01 + 0.1 - 0.1 == 0.01
>> False
>
> Do you know if there's a way to construct an example where
>
> i/k != (n*i)/(n*k)
>
> with preferrably small integers i, k, and n?

There wouldn't be for small integers. The simplest possible way for
Python to implement the division is to convert both numerator and
denominator to float before dividing with floating point. For integers
up to ~10**16 the conversion to float will be exact. IEEE 754 requires
that the divisions would always give the same result since it should
give the true result correctly rounded: both divisions should give the
same result if the true ratio of the floats is the same.

Actually looking here:
https://github.com/python/cpython/blob/3.7/Objects/longobject.c#L3835
that is exactly what happens for small integers. Also it looks as if
the algorithm for large integers is designed to compute the true
result correctly rounded as well.

As it mentions in the code though "results may be subject to double
rounding on x86 machines that operate with
the x87 FPU set to 64-bit precision." What that means is that on some
32 bit CPUs that don't have SSE2 you may see results that are rounded
differently.

So leaving aside older hardware I don't think there will be a case
where i/k != (n*i)/(n*k). All the same I prefer not to use floating
point for exact calculations and I would always recommend that a
beginner think of floating point operations as inexact.

> Python's integer division
> algorithm defeats my naive attempts ;)

I haven't tried to properly understand the code in long_true_divide
but it definitely looks like whoever wrote it knew what they were
doing :)

Cheers,
Oscar


More information about the Tutor mailing list