[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-smalltalk] Interesting Float to Fraction conversion
From: |
Paolo Bonzini |
Subject: |
Re: [Help-smalltalk] Interesting Float to Fraction conversion |
Date: |
Fri, 27 Oct 2006 08:25:59 +0900 |
User-agent: |
Thunderbird 1.5.0.7 (Macintosh/20060909) |
With the included patch, I get:
st> x := 1.14474205677314q-13.
st> x asFraction printNl.
st> (x asFraction - x) printNl!
2931673387916173/25609903738315777422401732608
1.40129846432481707092372958329q-45
That's pretty good.
Thanks,
Paolo
--- orig/kernel/Float.st
+++ mod/kernel/Float.st
@@ -221,7 +221,7 @@ asFraction
"Convert the receiver into a fraction with a good (but undefined)
approximation"
- | a x n2 d2 n1 d1 n0 d0 eps abs |
+ | a x n2 d2 n1 d1 n0 d0 eps abs gcd |
self checkCoercion.
@@ -232,8 +232,8 @@ asFraction
n1 := d0 := 0.
n0 := d1 := 1.
- abs := self abs.
- eps := self class epsilon * 1024. "Number out of a hat"
+ abs := self abs timesTwoPower: self exponent negated.
+ eps := self class epsilon.
x := abs.
[ a := x truncated.
@@ -245,6 +245,14 @@ asFraction
((self coerce: n0) / (self coerce: d0) - abs) abs < eps ]
] whileFalse.
+ self abs < 1
+ ifTrue: [ d0 := d0 * (2 raisedToInteger: self exponent negated) ]
+ ifFalse: [ n0 := n0 * (2 raisedToInteger: self exponent) ].
+
+ gcd := n0 gcd: d0.
+ n0 := n0 quo: gcd.
+ d0 := d0 quo: gcd.
+
^Fraction
numerator: (self < 0 ifTrue: [ n0 negated ] ifFalse: [ n0 ])
denominator: d0