Bitten by my C/Java experience

Chris Angelico rosuav at gmail.com
Fri May 8 07:32:01 EDT 2015


On Fri, May 8, 2015 at 8:47 PM, Albert van der Horst
<albert at spenarnc.xs4all.nl> wrote:
> In article <mailman.96.1430761253.12865.python-list at python.org>,
> Chris Angelico  <rosuav at gmail.com> wrote:
>>On Tue, May 5, 2015 at 3:32 AM, Irmen de Jong <irmen.NOSPAM at xs4all.nl> wrote:
>>> That is a broad question, but one thing that comes to mind is the
>>current (python 3)
>>> behavior of integer division. It gives the exact result and doesn't
>>truncate to integers:
>>>
>>>
>>>>>> 5/4
>>> 1.25
>>
>>Using the word "exact" around non-integer values can be a little
>>ambiguous, since floats are often inexact. But yes, int/int -> float,
>>and yes, it WILL bite C programmers.
>
> This should not be presented as a somewhat arbitrary decision.

I didn't, but my main point was that "exact" is a poor choice of word.

> Formerly we had
>
> 3e0/4e0
> 0.75
>
> and
>
> 3/4
> 0
>
> So the / operator worked on reals giving reals and integers
> giving integers. Great if you're used to it, but sometimes a pitfall.
> Also in practice it sometimes leads to rounding in unexpected places.
> The greatest disadvantage is when you have i and j and want their
> ratio. You have to do something like (real)i/j which feels unnatural.
> So we need two different division operators on the integers.
>
> Solution:
> introduce // for integer by integer given integer, giving the
> quotient (with a possible remainder).
> Now / is free to be used for the more rational  "i/j gives a ratio",
> i.e. a real number.

Where's that "i.e." come from? Why shouldn't i/j yield a Fraction, for
instance? That would be every bit as logical, and would mean we
effectively get "fraction literals" in their most obvious and natural
form. I can accept that int/int should yield something capable of
storing non-integral values, but I don't see that it absolutely has to
be IEEE floating point. However, that point has been much argued, and
it's definitely not changing now.

> Bottom line
> 3e0/4e0 and 3/4 gives the same result. It is nice to no longer
> have to be very careful in floating point calculation to avoid
> integer constants.
>
> On the other hand integer division is still available to solve
> the familiar egg-farm problems:
>
> I have 103 eggs. 12 eggs go in a box. How many boxes can I fill?

Of course they do... but you still actually have a difference. Compare:

>>> (1<<1000)//(1<<10)
10463951242053391806136963369726580181263718864311851635192874886429209483641954321222640418122029864527291727710479949464718215680589004332016189037791576956967351342601788071700268169006221818240189631008834448226154239518944108944497601509840881752510934060240763835605888507473266002770708660224

>>> (1<<1000)//(2.0**10)
1.0463951242053392e+298

>>> (1<<2000)//(2.0**10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: int too large to convert to float

So you do still need to worry about whether, with integer division,
you're working with integers or floats. Lots of programmers wish they
could just ignore all these problems and they'll go away, but floats
have inexactitude and range limits, where ints have neither (and
Fraction and Decimal values have their own notables), and ultimately,
you're going to have to know what data type your numbers are. That's
why I think it'd be better to have int/int -> Fraction; you might have
shocking performance, but then you can simply tell people to use
float() to speed up calculations at the expense of precision. At least
operations between int and Fraction are guaranteed to maintain
precision.

ChrisA



More information about the Python-list mailing list