[squeak-dev] asApproximateFraction[AtOrder:]

Eliot Miranda eliot.miranda at gmail.com
Mon Apr 23 20:59:45 UTC 2018


Hi Tim,

On Mon, Apr 23, 2018 at 1:34 PM, tim Rowledge <tim at rowledge.org> wrote:

> Do you normally want your fraction precise to an actual epsilon or to a
> fraction of the real value?
>
> Actually I guess that you could make a % value by working out the integer
> part, approximating the epsilon from that and using your method, so go for
> it. Not that I'm a numerics geek by any stretch.
>

 So you'd rather see

asApproximateFraction
"Answer a Fraction approximating the receiver. This conversion uses the
continued fraction method to approximate a floating point number."

^self asApproximateFractionToEpsilon: self abs / 1.0e6

?  Seems to work well:


| them |
them := (1 to: 6) collect: [:po10| (1 / ((10 raisedTo: po10) * 3)) asFloat].
them collect: [:fraction| fraction asApproximateFractionToEpsilon: fraction
/ 1.0e6] {(1/30) . (1/300) . (1/3000) . (1/30000) . (1/300000) .
(1/3000000)}

| them |
them := (1 to: 6) collect: [:po10| (1 / ((10 raisedTo: po10) / 3)) asFloat].
them collect: [:fraction| fraction asApproximateFractionToEpsilon: fraction
/ 1.0e6]
 {(3/10) . (3/100) . (3/1000) . (3/10000) . (3/100000) . (3/1000000)}

Float classPool associations
select: [:assoc| assoc value isFloat and: [assoc value isFinite and: [assoc
value fractionPart ~= 0]]]
thenCollect: [:assoc|
assoc key -> (assoc value asApproximateFractionToEpsilon: assoc value /
1.0e6)] {#Ln2->(1143/1649) . #Halfpi->(355/226) . #ThreePi->(1065/113) .
#RadiansPerDegree->(71/4068) . #Epsilon->(1/1000000000000) .
#MaxValLn->(16325/23) . #Ln10->(624/271) . #Pi->(355/113) .
#Sqrt2->(1393/985) . #Twopi->(710/113) . #E->(1264/465)}


So I'm for

asApproximateFraction
       "Answer a Fraction approximating the receiver. This conversion uses
the
       continued fraction method to approximate a floating point number."

       ^self asApproximateFractionToEpsilon: (self / 1e6) abs

talking in numerical analysis ignorance...



> > On 23-04-2018, at 1:23 PM, Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
> >
> > Hi All,
> >
> >     asApproximateFraction isn't that useful.  It is based on
> asApproximateFractionAtOrder:, which gives you the best fraction it can
> find up to order.  e.g.
> >
> > testContinuedFractions
> >       self assert: (Float pi asApproximateFractionAtOrder: 1) = (22/7).
> >       self assert: (Float pi asApproximateFractionAtOrder: 3) = (355/113)
> >
> > Here's 32-bit Float 1/3:
> >
> > ((FloatArray new: 1) at: 1 put: 1/3; at: 1) 0.3333333432674408
> >
> > ((FloatArray new: 1) at: 1 put: 1/3; at: 1) asApproximateFraction
> (11184811/33554432)
> >
> > That's not what I expected :-).  The problem is that
> asApproximateFractionAtOrder: is great if you know the number you're
> dealing with, but if you don't then it'll give you too much information.
> >
> > [This value comes up in the vm parameters system report page, where 1/3
> is the ratio of growth to heap size above which a full GC is performed,
> i.e. by default every time a scavenge causes the heap grows by 1/3 from the
> last time a full GC was performed, the system will do a full GC.  It would
> be great to report this as 1/3, not 0.33333298563957214, which is what's
> emerging from the C code in the VM].
> >
> > Let's get a feeling for orders; they're effectively negative powers of
> 10:
> >
> > (1 to: 20) collect: [:order| | f |
> > { order. (f := Float pi asApproximateFractionAtOrder: order). f asFloat.
> (f asFloat - Float pi) abs}]
> > {{1 . (22/7) . 3.142857142857143 . 0.0012644892673496777}.
> >  {2 . (333/106) . 3.141509433962264 . 8.32196275291075e-5}.
> >  {3 . (355/113) . 3.1415929203539825 . 2.667641894049666e-7}.
> >  {4 . (103993/33102) . 3.1415926530119025 . 5.778906242426274e-10}.
> >  {5 . (104348/33215) . 3.141592653921421 . 3.3162805834763276e-10}.
> >  {6 . (208341/66317) . 3.1415926534674368 . 1.2235634727630895e-10}.
> >  {7 . (312689/99532) . 3.1415926536189365 . 2.914335439641036e-11}.
> >  {8 . (833719/265381) . 3.141592653581078 . 8.715250743307479e-12}.
> >  {9 . (1146408/364913) . 3.141592653591404 . 1.6107115641261771e-12}.
> >  {10 . (4272943/1360120) . 3.141592653589389 . 4.04121180963557e-13}.
> >  {11 . (5419351/1725033) . 3.1415926535898153 . 2.220446049250313e-14}.
> >  {12 . (80143857/25510582) . 3.1415926535897927 . 4.440892098500626e-16}.
> >  {13 . (245850922/78256779) . 3.141592653589793 . 0.0}.
> >  {14 . (817696623/260280919) . 3.141592653589793 . 0.0}.
> >  {15 . (19052873251/6064717916) . 3.141592653589793 . 0.0}.
> >  {16 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.
> >  {17 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.
> >  {18 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.
> >  {19 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.
> >  {20 . (19870569874/6324998835) . 3.141592653589793 . 0.0}}
> >
> >
> > More useful would be something like:
> >
> > asApproximateFractionToEpsilon: epsilon
> >       "Answer a Fraction approximating the receiver. This conversion
> uses the
> >       continued fraction method to approximate a floating point number."
> >
> >       1 to: 12 do:
> >               [:order| | fraction |
> >                fraction := self asApproximateFractionAtOrder: order.
> >                (fraction - self) abs <= epsilon ifTrue:
> >                       [^fraction]].
> >       ^ self asApproximateFractionAtOrder: 0
> >
> > and then instead of
> >
> > asApproximateFraction
> >       "Answer a Fraction approximating the receiver. This conversion
> uses the
> >       continued fraction method to approximate a floating point number."
> >
> >       ^ self asApproximateFractionAtOrder: 0
> >
> > one could have
> >
> > asApproximateFraction
> >       "Answer a Fraction approximating the receiver. This conversion
> uses the
> >       continued fraction method to approximate a floating point number."
> >
> >       ^self asApproximateFractionToEpsilon: 1e-6
> >
> > And hence
> >
> > { 0.0. 0.333. 0.5. 1.0. Float pi . ((FloatArray new: 1) at: 1 put: 1/3;
> at: 1) } collect:
> >     [:n| n asApproximateFractionToEpsilon: 1e-6]
> > {0 . (333/1000) . (1/2) . 1 . (355/113) . (1/3)}
> >
> > Votes for or against changing asApproximateFraction to use
> asApproximateFractionToEpsilon:? (asApproximateFraction has no senders
> into base image)
> >
> > Suggestions for a selector that would use self
> asApproximateFractionToEpsilon: 1e-6 (less clumsy than e.g.
> asUsefulApproximateFraction).
> >
> > _,,,^..^,,,_
> > best, Eliot
> >
>
>
> tim
> --
> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim
> Spell checkers at maximum!  Fire!
>
>
>
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20180423/e3119d19/attachment.html>


More information about the Squeak-dev mailing list