[Edu-sig] Re: rationals

Guido van Rossum guido@python.org
Thu, 10 Oct 2002 16:24:58 -0400


> >Except I don't like the 3r2 notation very much.  In my version it
> >would become 3/2r, or 3r/2; parsed as 3 / 2r and 3r / 2, respectively.
> 
> Not clear if you mean 3r is by itself a rational (=3/1)

Yes.

> as in:
> 
>    >>> a = 3r
>    >>> a/2r
> 3/2
> 
> or would that be 3/2r ?

It would probably print that, yes.

> Entering 3r/2 on a command line looks to me like an invocation
> of division between a rational (3r) and an integer (2), and so
> would return 1.5 (float), i.e.
> 
>    >>> 3r/2
> 1.5

Why?  A binary operator involving an int or long and a rational should
return a rational, IMO -- the int or long can always be cast to
rational, and the result is exact.

> >And I'd also support 1.5r as a way to spell the same value.
> 
> Makes sense.
> 
> I get confused when I try to see / used both as an operator, and
> as part of the name of a number.  Not sure if that's what you're
> doing.

You can see it either way and it doesn't make any difference for the
outcome.  Just like we write negative numbers as -3 which is
technically the minus operator applied to the positive constant 3, or
complex constants as 2+1j which is technically a float constant plus
an irrational constant.

> Would you go:
> 
>    >>> 1.5 .__rational__()
> 3/2r

I'm not sure I'd like to add __rational__ to all numeric types to
convert things into rationals.

I'm also not sure that converting arbitrary floats to rationals should
be a standard conversion.

>    >>> 3/2r .__float__()
> 1.5

Definitely, but please write that as float(3/2r).

> Perhaps you could do a short dialog in Python along the lines of:
> 
>     >>> a = 3r2
>     >>> b = 1r2
>     >>> a * b
> 3r4
>     >>> float(a*b)
> 0.75
>     >>> a + 2
> 5r2
>     >>> a / 2
> 3r4
> 
> showing how it'd look in your implementation.

I have no implementation. :-)

But it would look like this:

  >>> a = 3/2r
  >>> b = 1/2r
  >>> a * b
  (3/2r)
  >>> float(a*b)
  0.75
  >>> a + 2
  (5/2r)
  >>> a / 2
  3/4r
  >>> 

(I'm not sure about the parens, but complex uses them in a similar
situation.)

> Note:  I'm deviating from the policy that rat / int --> float
> in the last line.  Not sure if this is a good idea.  Maybe:
> 
>     int   / int   --> float     (float//float --> int)
>     float / int   --> float     (int//int     --> int)
>     rat   / int   --> rat   (?) (rat//rat     --> int)
>     rat   / float --> float
>     rat   / rat   --> rat

Exactly.  int/rat should also be a rat.

> In other words, maybe it makes sense for / to coerce an int or
> a long into a rat if the other arg is a rat.  This wouldn't
> break code, as rat is a new type that couldn't get created by
> old pre-rat code.

Right.

> Coercion:
> 
> rat(3.1)    --> 31/10r   (?)

I don't like this, but maybe it's okay.  It's up to the rat()
constructor though, the float needn't know anything about this.

> rat(2)      --> 2r
> float(2/3r) --> 0.66666666666666663

Right.

> rat() or rational()  ?

I think rat() is good -- after all I shortened 'dictionary' to 'dict'...

--Guido van Rossum (home page: http://www.python.org/~guido/)