Floats and Fractions

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Floats and Fractions

Ian Bartholomew-4
Float implements two methods for converting itself into a Fraction -
#asApproximateFraction and #asTrueFraction. Float also implements the
polymorphic #asFraction which defaults to using #asApproximateFraction.  I'm
thinking of changing this default to #asTrueFraction as -

- I usually want to convert without loss of precision as the default.
- #asApproximateFraction is, surprisingly, 7 to 15 times slower than
#asTrueFraction

The only downside I've found is that "aReallyReallyBigNumber asTrueFraction
asFloat" sometimes causes an overflow whereas #asApproximateFraction
doesn't.

The question is, have I missed something or is #asApproximateFraction a bit
pointless?.

Regards
    Ian


Reply | Threaded
Open this post in threaded view
|

Re: Floats and Fractions

Ian Bartholomew-4
> The question is, have I missed something or is #asApproximateFraction a
> bit pointless?.

To answer myself - no it's not. _Sometimes_ it is more accurate than
#asTrueFraction and _sometimes_ it's not.

Sigh. I'm going to have to think about this a bit more!.

Please ignore the previous post.

Ian / 100


Reply | Threaded
Open this post in threaded view
|

Re: Floats and Fractions

Blair McGlashan
Ian

You wrote in message news:ot4%6.1263$[hidden email]...
> > The question is, have I missed something or is #asApproximateFraction a
> > bit pointless?.
>
> To answer myself - no it's not. _Sometimes_ it is more accurate than
> #asTrueFraction and _sometimes_ it's not.

#asApproximateFraction is never more "accurate" than #asTrueFraction (though
I know what you mean). #asTrueFraction precisely represents the exact value
of the Float as the equivalent Fraction. The problem is that #asTrueFraction
is often _too_ accurate - Floats are an imprecise representation so one may
end up with more precision in the Fraction than one wants. For example 0.1
cannot be represented precisely as a Float, so when one converts it to a
Fraction using #asTrueFraction the result is a Fraction equivalent to the
Float approximation of 0.1, in fact (3602879701896397/36028797018963968). As
this is probably not what one wants in general (!), the default conversion
is #asApproximateFraction (which does yield 1/10).

It would be helpful if the method comments explained this.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Floats and Fractions

Chris Uppal-3
In reply to this post by Ian Bartholomew-4
Ian,

> - I usually want to convert without loss of precision as the default.
> - #asApproximateFraction is, surprisingly, 7 to 15 times slower than
> #asTrueFraction

The relative speed seems to depend on the machine as well as the number to
be converted.  I have no idea why this should be.

> The only downside I've found is that "aReallyReallyBigNumber
asTrueFraction
> asFloat" sometimes causes an overflow whereas #asApproximateFraction
> doesn't.

Looking at the code, I can't see any way that it can overflow.  Certainly it
shouldn't have to since all it's doing is bit-twiddling the binary
representation of Float into a pair of (possibly Big) Integers.  Can you
post an example ?

[in your follow-up post]
> To answer myself - no it's not. _Sometimes_ it is more accurate than
> #asTrueFraction and _sometimes_ it's not.

Again, I can't see any reason why #asTrueFraction should ever be less than
perfectly accurate (if the bit-twiddling is correct, I haven't tried to
validate it).  What are your counter-examples ?  I suppose there may be
cases where it would *look* less accurate if the initial (textual) float you
started with didn't have an exact binary representation, and then the
approximation process in #asApproximateFraction happened to cancel-out the
approximation involved in creating the float in the first place.

> The question is, have I missed something or is #asApproximateFraction a
bit
> pointless?.

I don't think you have, and I think it is.  (Subject to the caveat that your
examples of failure may indicate bugs.)

>     Ian

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Floats and Fractions

Ian Bartholomew-4
Chris,

> The relative speed seems to depend on the machine as well as the number to
> be converted.  I have no idea why this should be.

I wrote a more logical and, I thought, more efficient version of
#asApproximateFraction and it turned out to be about 20 times slower than
the existing version <g>. I decided to move on ....

> Looking at the code, I can't see any way that it can overflow.  Certainly
> it shouldn't have to since all it's doing is bit-twiddling the binary
> representation of Float into a pair of (possibly Big) Integers.  Can you
> post an example ?

It wasn't the #asTrueFraction that was failing but the subsequent #asFloat.
I can't find the code I had yesterday but the following shows what was
happening.

#asTrueFraction can end up with some pretty large LargeIntegers as numerator
and denominator. When you try to convert one of these Fractions to a Float
it does so by converting the numerator and denominator to floats and then
dividing them. The problem was that converting very LargeIntegers to Float
can fail in LargeInteger>>asFloat when the primitive can't cope and forces
the Smalltalk code to be evaluated. If the LargeInteger is close to MaxFloat
then the multiplication by 256.0 can overflow.

1975308624000000076961124327420095076281907586883960015302339297089638593475
6197823430991503856376507408663010846318067059838771832014640726638865085737
6969532393014279556097685513394294369336308422074380505521165692608066869311
2421295779158361675359672631387801645846267102638099106934537524510784316464
16896 asFloat

(You'll have to strip the crs out)

#asApproximateFraction always worked simply because the LargeIntegers never
got as large.

> Again, I can't see any reason why #asTrueFraction should ever be less than
> perfectly accurate (if the bit-twiddling is correct, I haven't tried to
> validate it).  What are your counter-examples ?

0.1 asTrueFraction (3602879701896397/36028797018963968)
0.1 asApproximateFraction (1/10)

"accurate" is probably a bad choice of word as _both_ the above are
accurate. The first is an accurate representation of the Float 0.1 and the
second is accurate mathematically. I was trying to get the mathematical
accuracy of the second with the precision of the first (i.e. calculations
and comparisons would be accurate!)

> > The question is, have I missed something or is #asApproximateFraction a
> > bit pointless?.
>
> I don't think you have, and I think it is.  (Subject to the caveat that
> your examples of failure may indicate bugs.)

Pointless was probably a bit harsh. Neither method really did what I wanted
so I've done it a different way (see other thread)

Ian