From: "Dennis E. Hamilton" <dennis.hamilton@acm.org> To: <edu-sig@python.org> Subject: RE: [Edu-sig] Re: rationals Date: Fri, 11 Oct 2002 18:25:24 -0700
The biggest difference is that some floating-point calculations that will converge (disappear at 0 or converge on a fixed value) will not terminate in rational computation.
Since this sort of thing is not a very good way to use floats either, it should provoke more-appropriate numerical techniques.
Right--I thought that the more accepted technique was to (if we're going for zero) pick an epsilon, and then exit when abs(arg)<epsilon (and if we converge to something else, perhaps to pick an epsilon, and quit when the last ten arguments were within epsilon of each other). re: int/int --> float Wha? But the definition of rational is the set of numbers that can be represented as int/int! I understand the speediness argument, but please, let us not go float unless we coerce there! I thought the whole point of the rational thread was for "1/3" to simplify to something meaningful. Would it work (just throwing this out, having no real idea of how rats are implemented elsewhere) to set each of the numerator and the denominator to be a dict of the prime factorization thereof (assuming we are working with <100 digit numerals)? Or we could say that "int/int --> float, int//int --> int, and int///int --> rational". But this feels like a dangerous road. It'll be neat to have a set of numbers, though, where division is cheaper than addition.
At 06:24 AM 10/12/2002 -0400, Lloyd Hugh Allen wrote:
re: int/int --> float Wha? But the definition of rational is the set of numbers that can be represented as int/int! I understand the speediness argument, but please, let us not go float unless we coerce there!
An argument for int/int --> float is that this keeps preserves closure between existing Python types and doesn't stick a big "under construction sign" in the language for many versions to come. Then rationals can be added without disruption, as it'd take new syntax (e.g. 1r/3) to invoke them, leaving older code to run as it always has. Given that you can go either way with int/int, I think the above argument maybe tilts the balance in favor of int/int --> float. Kirby PS: The idea of storing prime factors internally is not practical, as nobody knows how to get the prime factors of really big integers quickly, whereas rational arithmetic (including reducing to lowest terms), *is* possible with these same big integers. Requiring an internal dict of primes would put a ceiling on rationals that doesn't really need to be there. The beauty of Euclid's Algorithm is it finds the gcd *without* needing a prime factorization -- which is why it should be taught earlier, so kids don't get the impression that those "factor trees" are necessary when finding the gcd of two composites. NOTE: Althought it's true the pure Scheme supports int/int -> rational, PLT Scheme goes with int/int -> float in many of its teaching modes (this is a language where there *is* one of those "environment switches" such as some have proposed for Python). Examples: Welcome to DrScheme, version 201. Language: Advanced Student.
(/ 3 4) 0.75
Welcome to DrScheme, version 201. Language: Textual (MzScheme, includes R5RS).
(/ 3 4) 3/4
Also, in J (evolved from APL), int/int --> float is the norm: 3 % 4 NB. % is the div operator 0.75 but make either argument rational, leaving the other int, and you get a rational result: 3x % 2 3r2 3 % 2x 3r2 This latter mode could be true for Python too.
3 / 4 0.75 3r / 4 3/4r
The alternative you propose would look like this (I presume):
3 / 4 3/4r 3. / 4 0.75 3 / 4. 0.75
Basically, it boils down to whether we have to use a . (dot) or an r to coerce a float or rational result respectively. Kirby
Basically, it boils down to whether we have to use a . (dot) or an r to coerce a float or rational result respectively.
Except of course, in reality, the values are in variables, and possibly we don't even know the types of those variables. So then you can write (x * 1r) / y to force a rational as long as x and y are ints or rationals; this yields a float or complex if either x or y is that. Aside: you could also use (x + 0r) / y but if x is an IEEE float with the value -0, adding 0 turns it into +0, while multiplying by 1 keeps the sign the same. The distinction between +0 and -0 may be important when it is the result of underflow. For example:
x = -1.0 while x: ... x = x*0.5 ... x -0.0 x*1 -0.0 x+0 0.0 x < 0 False
--Guido van Rossum (home page: http://www.python.org/~guido/)
participants (3)
-
Guido van Rossum
-
Kirby Urner
-
Lloyd Hugh Allen