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