Fraction hackers...
Florin Mateoc
Florin at integral.com
Thu Sep 9 18:42:34 UTC 1999
I would propose instead:
= aNumber
aNumber isFraction
ifTrue: [^ (numerator * aNumber denominator) =
(aNumber numerator * denominator)].
^ aNumber adaptToFraction: self andSend: #=
For reference the (new) current implementation is
= aNumber
aNumber isNumber ifFalse: [^ false].
aNumber isFraction
ifTrue: [numerator = 0 ifTrue: [^ aNumber numerator = 0].
^ (numerator * aNumber denominator) =
(aNumber numerator * denominator)].
^ aNumber adaptToFraction: self andSend: #=
The two removed tests ("isNumber" and "numerator = 0") are on the common
path although they are for exceptional cases.
The second one is simply useless, we could as well add another one for
"aNumber numerator = 0" and then then one for "denominator = 1" and then one
for "aNumber denominator = 1".
The first one is dealt with by #adaptToFraction:andSend: as for all the
other Fraction arithmetic messages, so this is not only a common case
optimization, it's also a consistency issue. This approach would allow us to
compare say a String representation with a Fraction. Last but not least I
don't like the #isNumber message ;-). Obviously #isFraction is a different
story here because it complements #adaptToFraction:andSend:
We may also want to add Object>>adaptToNumber:andSend:
adaptToNumber: rcvr andSend: selector
^self perform: selector with: rcvr
Since Object does not know how to adapt to a Number and it makes no sense to
send the message to the receiver again (with an unmodified argument), we
send it to self instead. This obviously works for #= but maybe there are
better solutions, maybe we want it to break instead when we compare apples
with oranges.
And while we are talking about Fraction, I would suggest the following
implementation for #reduced that complements the new #= implementation
reduced
| gcd |
numerator = 0 ifTrue: [^0].
(gcd _ numerator gcd: denominator) == denominator ifTrue:
[^numerator // gcd].
gcd == 1 ifFalse: [
numerator _ numerator // gcd.
denominator _ denominator // gcd]
instead of the current
reduced
| gcd numer denom |
numerator = 0 ifTrue: [^0].
gcd _ numerator gcd: denominator.
numer _ numerator // gcd.
denom _ denominator // gcd.
denom = 1 ifTrue: [^numer].
^Fraction numerator: numer denominator: denom
The proposed implementation does not create a new Fraction object, it
modifies self instead. #reduced is a private message and a reduced fraction
refers to the same conceptual fraction (and with the new #= method they
would also be equal). I cannot think of a situation where we would want to
hold onto the unreduced representation as well.
Cheers,
Florin
> -----Original Message-----
> From: Dan Ingalls [SMTP:Dan.Ingalls at disney.com]
> Sent: Wednesday, September 01, 1999 8:25 PM
> To: squeak at cs.uiuc.edu
> Subject: Fraction hackers...
>
> In update 1400, I changed the implementation of Fraction = to tolerate
> improper fractions. I think it's the best fix to make (1/2) = (3/6). VW
> fails this, and Squeak used to as well (for the same reason). If you like
> to work with Fractions, I would appreciate it if you would check that I
> haven't broken anything obvious. Thanks.
>
> - Dan
>
More information about the Squeak-dev
mailing list
|