Future division patch available (PEP 238)

Marcin 'Qrczak' Kowalczyk qrczak at knm.org.pl
Sun Jul 22 14:06:27 EDT 2001


Sun, 22 Jul 2001 12:55:29 +0100, Stephen Horne <steve at lurking.demon.co.uk> pisze:

>>All arithmetic operators and functions like divmod, except /, have the
>>property that the value of the result, as long as it's not an error,
>>depends only on the values of arguments - not on their types.
> 
> Not true.
> 
> 1 + 1 == 2
> 1.0 + 1.0 == 2.0
> 1L + 1L == 2L

This is my point: 2 == 2.0 and 2.0 == 2L. The value is the same,
only represented in different types.

> It is a convenience - it does not make integers equivalent to floats.

Sure, but after fixing / an integer can be used when a float is
expected without surprise.

> I see no reason good reason to weaken Python by discarding strong
> typing.

It's not discarding strong typing. Proper strong typing would disallow
/ on integers at all: it's not a field after all, only a ring. Integer
division is not a special case of real division.

> I would like a 'mod' operator, I admit, but it wouldn't be the same as
> the current '%' operator (and the mod part of divmod) because they
> provide the remainder - not the modulo - which is different when the
> arguments include negative numbers.

No, they all provide the modulo, i.e. divmod(-123, 10) == (-13, 7),
(-123) % 10 == 7, (-123) / 10 == -13.

> I'd therefore like 'mod' and 'rem' - like Ada

Or like Haskell. It's ok to have all six (div, mod, divmod, quot, rem,
quotrem), but I don't think that Guido wants to add so many operators.

>>- / applied to ints or longs should return the exact result as a rational.
> 
> Support for rationals is a good idea, but I'd prefer to see them
> as a separate type.

Surely I want a separate type.

> When working with rationals or floats or whatever, you should get
> a result appropriate to that type.

It's not that simple, e.g. exp(1/2) should return a float. Generally
if an operation is not applicable to the given domain, there are two
choices: report an error or promote the argument to a more appropriate
domain. Given that Python already chose promotion in some contexts and
that literals won't have a type depending on the context, IMHO it's
more convenient to do the promotion. Practicality beats purity. This
implies that / on ints promote them to something, and rationals are
good here because the result is always correct.

>>- When rationals and floats are mixed, the result is a float.
> 
> Any float is merely an alternative representation of a rational,
> whether it is a binary float or a decimal float.

But when floats are used, the intent is that the value is not exact:
analog, not digital. So results of operations performed on floats
are inexact too.

> 0.0001 == 1/10000
> 
> Wherever you put the point, it is a simple matter to derive an integer
> numerator and denominator to represent a particular float exactly as a
> rational - even when the exponent (the * base**n part) is included.

This is the question of what 0.0001 should mean: rational or float.
I said that I don't have a strong position. I think that rationals
here is a more idealistic decision (it doesn't lose information,
one can always convert it to float but conversion in the opposite
direction would not work). Floats might be more practical if rationals
already had a syntax (namely 1/3), especially as this is what these
literals mean now. So it's ok for me when they are floats.

> Logically, operations with mixed float and rational arguments should
> give rational results - the float argument can be accurately
> converted, and the result is less likely to have lost precision.

Too late: it has already lost its precision because input was a float.
I assume that one would *not* use floats in case the value can be
represented exactly and the intent is to represent it exactly. One
should use a rational or integer in such case. Floats are inexact
by nature.

> The only real values that cannot be represented exactly as rationals
> are irrational numbers - such as pi, sqrt(2) and e. These values
> equally cannot be represented exactly as floats.

But floats are used to represent their approximations. We have two
choices about the meaning of pi+1/2: either 3.641592653589793 or
3+180592277226915/281474976710656. I think that the former is a better
choice; it's inexact anyway, so we should not pretend that it's exact.

> Of course, this then opens a major can of worms - rational versions
> of trig functions and similar would not be realistic, and therefore
> you'd get lots of implicit conversions from floats to rationals
> (rationals being more general than floats) only to have to convert
> back again for the trig functions, and so on.

That's why I would do it in the opposite direction.

>>  Decimal floats should not be necessary: they are inexact
>>  like binary floats and slow like rationals.
> 
> Floats are not slow on modern hardware.

This is what I said.

When you want speed, use floats. When you want correctness, use
rationals. You can't have both. Decimal floats provide neither.

-- 
 __("<  Marcin Kowalczyk * qrczak at knm.org.pl http://qrczak.ids.net.pl/
 \__/
  ^^                      SYGNATURA ZASTĘPCZA
QRCZAK



More information about the Python-list mailing list