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 |
> 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 |
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 |
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 |
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 |
Free forum by Nabble | Edit this page |