Fraction.st
changeset 6576 c28cdeb0bfb0
parent 6571 101905a14870
child 6646 875d9668d82b
--- a/Fraction.st	Tue Jun 11 23:44:10 2002 +0200
+++ b/Fraction.st	Tue Jun 11 23:45:07 2002 +0200
@@ -230,7 +230,7 @@
                     denominator:denominator)
     ].
     aNumber isFraction ifTrue:[
-        aNumber isFixedPoint ifFalse:[  "/ the value was corrent, but the scale is lost
+        aNumber isFixedPoint ifFalse:[  "/ the value was correct, but the scale is lost
             n := aNumber numerator.
             d := aNumber denominator.
 
@@ -245,7 +245,7 @@
         ]
     ].
     (aNumber isMemberOf:Float) ifTrue:[
-        ^ aNumber + (numerator asFloat / denominator asFloat)
+        ^ aNumber + self asFloat
     ].
 
     ^ aNumber sumFromFraction:self
@@ -413,23 +413,46 @@
 asFloat
     "return a float with (approximately) my value"
 
-    |num den numB denB bits|
+    |num den numShift denShift bits|
 
     (numerator class == SmallInteger and:[denominator class == SmallInteger]) ifTrue:[
         ^ (numerator asFloat) / (denominator asFloat)
     ].
 
-    "Do it the hard way: make numbers smaller and redo this on the quotient"
+    "Do it the hard way: reduce magnitude and undo reduction on the quotient"
 
-    bits := Float zero numberOfBits * 2. "number of bits to preserve (conservative)"
+    bits := Float precision * 2.    "number of bits to preserve (conservative)"
     num := numerator abs.
-    den := denominator abs.
-    numB := num highBit - bits.
-    numB > 0 ifTrue:[num := num bitShift:numB negated].
-    denB := den highBit - bits.
-    denB > 0 ifTrue:[den := den bitShift:denB negated].
+    numShift := bits - num highBit. "(num highBit - bits) negated"
+    numShift < 0 ifTrue:[num := num bitShift:numShift] ifFalse:[numShift := 0].
+
+    den :=  denominator.
+    denShift := bits - den highBit. "(den highBit - bits) negated"
+    denShift < 0 ifTrue:[den := den bitShift:denShift] ifFalse:[denShift := 0].
+
+    ^ (num asFloat / den asFloat) * (2.0 raisedToInteger:denShift-numShift) * (num sign)
 
-    ^ (num asFloat / den asFloat) * (2.0 raisedToInteger:numB-denB) * (num sign)
+    " 
+      (5/9) asFloat
+      (-5/9) asFloat
+      (500000000000/900000000000) asFloat
+      (-500000000000/900000000000) asFloat
+      (500000000000/9) asFloat
+      (5/900000000000) asFloat
+      89012345678901234567 asFloat / 123456789123456789 asFloat
+      (89012345678901234567 / 123456789123456789) asFloat
+
+      (
+       180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
+        /
+       180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
+      ) asFloat
+
+      180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
+         asFloat /
+      180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
+         asFloat
+    "
 !
 
 asFraction
@@ -451,11 +474,19 @@
 !
 
 asShortFloat
-    "return a shortFloat with (approximately) my value"
+    "return a short float with (approximately) my value"
+
+    (numerator class == SmallInteger and:[denominator class == SmallInteger]) ifTrue:[
+        ^ (numerator asShortFloat) / (denominator asShortFloat)
+    ].
 
-    ^ (numerator asShortFloat) / (denominator asShortFloat)
+    ^ self asFloat asShortFloat
 
-    "Created: 17.4.1996 / 12:21:08 / cg"
+    "
+      (5/9) asShortFloat
+      (500000000000/900000000000) asShortFloat
+      (500000000000/9) asShortFloat
+    "
 !
 
 coerce:aNumber
@@ -691,12 +722,11 @@
 
     gcd := numerator gcd:den.
     (gcd ~~ 1) ifTrue:[
+        gcd < 0 ifTrue:[
+             gcd := gcd negated.
+        ].
         numerator := numerator // gcd.
         denominator := den := den // gcd.
-        den < 0 ifTrue:[
-            numerator := numerator negated.
-            den := denominator := den negated.
-        ].
         (den == 1) ifTrue:[^ numerator].
     ].
     ^ self
@@ -821,6 +851,6 @@
 !Fraction class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.55 2002-06-11 10:06:42 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.56 2002-06-11 21:45:07 stefan Exp $'
 ! !
 Fraction initialize!