<div dir="ltr"><div><div><div>Hi all,<br></div>I couldn't resist, and posted a version to the trunk ;)<br></div>We can have both (un)limited number of iterations and limited precision (it is limited by Float ulp / 2 anyway...).<br>I kept the default to 10 decimal places, but we can reduce it to 6 if we want to...<br><br></div><div></div></div><div class="gmail_extra"><br><div class="gmail_quote">2018-04-26 5:03 GMT+02:00 David T. Lewis <span dir="ltr"><<a href="mailto:lewis@mail.msen.com" target="_blank">lewis@mail.msen.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Wed, Apr 25, 2018 at 06:32:51PM -0700, Eliot Miranda wrote:<br>
> On Mon, Apr 23, 2018 at 8:06 PM, David T. Lewis <<a href="mailto:lewis@mail.msen.com">lewis@mail.msen.com</a>> wrote:<br>
> <br>
> > Hi Eliot,<br>
> ><br>
> > I think that the confusing behavior is is related to the interpretation of<br>
> > single<br>
> > precision floats in the VM when represented as double precision Float in<br>
> > Squeak.<br>
> ><br>
> > How about implementing #<wbr>asApproximateFractionFloatPrec<wbr>ision: to specify<br>
> > the<br>
> > assumed accuracy of the float when derived from single precision, but<br>
> > represented<br>
> > in the image as a double precision Squeak float?<br>
> ><br>
> <br>
> Thanks, David.  This looks good to me.  But I'm no expert here.  If I were<br>
> to put this into trunk I would modify asApproximateFraction: to<br>
> send asApproximateFractionAtOrder:<wbr>floatPrecision: directly.<br>
> <br>
<br>
</span>Oops, emails crossed in the ether. I just committed a small but important fix<br>
to the inbox, and I missed your suggestion.<br>
<br>
Should this go to trunk? If so I will add your change when merging.<br>
<br>
Dave<br>
<div class="HOEnZb"><div class="h5"><br>
> <br>
> > Thus:<br>
> ><br>
> >   (FloatArray new: 1) at: 1 put: 1/3; at: 1 ==> 0.3333333432674408 "single<br>
> > precision float cast from FloatArray to Squeak double precision"<br>
> ><br>
> >   0.3333333432674408 asApproximateFraction ==> (11184811/33554432) "bad,<br>
> > original default implementation assumes float double precision"<br>
> ><br>
> >   0.3333333432674408 asApproximateFractionFloatPrec<wbr>ision: 5 ==> (1/3)<br>
> > "better, limit precision when cast from single precision to double"<br>
> ><br>
> > An implementation is in the inbox in Kernel-dtl.1165.<br>
> ><br>
> > Note, orignal author for these methods has initials 'st' is, which<br>
> > according to<br>
> > SqueakMap is Samuel Tardieu (<a href="mailto:sam@rfc1149.net">sam@rfc1149.net</a>, home page<br>
> > <a href="https://rfc1149.net/sam.html" rel="noreferrer" target="_blank">https://rfc1149.net/sam.html</a>).<br>
> > Even for those of us not who may not be interested in numerical methods, I<br>
> > must<br>
> > highly recommend his references to rfc1149.<br>
> ><br>
> > Dave<br>
> ><br>
> ><br>
> > On Mon, Apr 23, 2018 at 01:23:03PM -0700, Eliot Miranda wrote:<br>
> > > Hi All,<br>
> > ><br>
> > >     asApproximateFraction isn't that useful.  It is based on<br>
> > > asApproximateFractionAtOrder:, which gives you the best fraction it can<br>
> > > find up to order.  e.g.<br>
> > ><br>
> > > testContinuedFractions<br>
> > > self assert: (Float pi asApproximateFractionAtOrder: 1) = (22/7).<br>
> > > self assert: (Float pi asApproximateFractionAtOrder: 3) = (355/113)<br>
> > > Here's 32-bit Float 1/3:<br>
> > ><br>
> > > ((FloatArray new: 1) at: 1 put: 1/3; at: 1) 0.3333333432674408<br>
> > ><br>
> > > ((FloatArray new: 1) at: 1 put: 1/3; at: 1) asApproximateFraction<br>
> > > (11184811/33554432)<br>
> > ><br>
> > > That's not what I expected :-).  The problem is that<br>
> > > asApproximateFractionAtOrder: is great if you know the number you're<br>
> > > dealing with, but if you don't then it'll give you too much information.<br>
> > ><br>
> > > [This value comes up in the vm parameters system report page, where 1/3<br>
> > is<br>
> > > the ratio of growth to heap size above which a full GC is performed, i.e.<br>
> > > by default every time a scavenge causes the heap grows by 1/3 from the<br>
> > last<br>
> > > time a full GC was performed, the system will do a full GC.  It would be<br>
> > > great to report this as 1/3, not 0.33333298563957214, which is what's<br>
> > > emerging from the C code in the VM].<br>
> > ><br>
> > > Let's get a feeling for orders; they're effectively negative powers of<br>
> > 10:<br>
> > ><br>
> > > (1 to: 20) collect: [:order| | f |<br>
> > > { order. (f := Float pi asApproximateFractionAtOrder: order). f asFloat.<br>
> > (f<br>
> > > asFloat - Float pi) abs}]<br>
> > > {{1 . (22/7) . 3.142857142857143 . 0.0012644892673496777}.<br>
> > >  {2 . (333/106) . 3.141509433962264 . 8.32196275291075e-5}.<br>
> > >  {3 . (355/113) . 3.1415929203539825 . 2.667641894049666e-7}.<br>
> > >  {4 . (103993/33102) . 3.1415926530119025 . 5.778906242426274e-10}.<br>
> > >  {5 . (104348/33215) . 3.141592653921421 . 3.3162805834763276e-10}.<br>
> > >  {6 . (208341/66317) . 3.1415926534674368 . 1.2235634727630895e-10}.<br>
> > >  {7 . (312689/99532) . 3.1415926536189365 . 2.914335439641036e-11}.<br>
> > >  {8 . (833719/265381) . 3.141592653581078 . 8.715250743307479e-12}.<br>
> > >  {9 . (1146408/364913) . 3.141592653591404 . 1.6107115641261771e-12}.<br>
> > >  {10 . (4272943/1360120) . 3.141592653589389 . 4.04121180963557e-13}.<br>
> > >  {11 . (5419351/1725033) . 3.1415926535898153 . 2.220446049250313e-14}.<br>
> > >  {12 . (80143857/25510582) . 3.1415926535897927 . 4.440892098500626e-16}.<br>
> > >  {13 . (245850922/78256779) . 3.141592653589793 . 0.0}.<br>
> > >  {14 . (817696623/260280919) . 3.141592653589793 . 0.0}.<br>
> > >  {15 . (19052873251/6064717916) . 3.141592653589793 . 0.0}.<br>
> > >  {16 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.<br>
> > >  {17 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.<br>
> > >  {18 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.<br>
> > >  {19 . (19870569874/6324998835) . 3.141592653589793 . 0.0}.<br>
> > >  {20 . (19870569874/6324998835) . 3.141592653589793 . 0.0}}<br>
> > ><br>
> > ><br>
> > > More useful would be something like:<br>
> > ><br>
> > > asApproximateFractionToEpsilon<wbr>: epsilon<br>
> > > "Answer a Fraction approximating the receiver. This conversion uses the<br>
> > > continued fraction method to approximate a floating point number."<br>
> > ><br>
> > > 1 to: 12 do:<br>
> > > [:order| | fraction |<br>
> > > fraction := self asApproximateFractionAtOrder: order.<br>
> > > (fraction - self) abs <= epsilon ifTrue:<br>
> > > [^fraction]].<br>
> > > ^ self asApproximateFractionAtOrder: 0<br>
> > ><br>
> > > and then instead of<br>
> > ><br>
> > > asApproximateFraction<br>
> > > "Answer a Fraction approximating the receiver. This conversion uses the<br>
> > > continued fraction method to approximate a floating point number."<br>
> > ><br>
> > > ^ self asApproximateFractionAtOrder: 0<br>
> > ><br>
> > > one could have<br>
> > ><br>
> > > asApproximateFraction<br>
> > > "Answer a Fraction approximating the receiver. This conversion uses the<br>
> > > continued fraction method to approximate a floating point number."<br>
> > ><br>
> > > ^self asApproximateFractionToEpsilon<wbr>: 1e-6<br>
> > ><br>
> > > And hence<br>
> > ><br>
> > > { 0.0. 0.333. 0.5. 1.0. Float pi . ((FloatArray new: 1) at: 1 put: 1/3;<br>
> > at:<br>
> > > 1) } collect:<br>
> > >     [:n| n asApproximateFractionToEpsilon<wbr>: 1e-6]<br>
> > > {0 . (333/1000) . (1/2) . 1 . (355/113) . (1/3)}<br>
> > ><br>
> > > Votes for or against changing asApproximateFraction to use<br>
> > > asApproximateFractionToEpsilon<wbr>:? (asApproximateFraction has no senders<br>
> > into<br>
> > > base image)<br>
> > ><br>
> > > Suggestions for a selector that would use self<br>
> > > asApproximateFractionToEpsilon<wbr>: 1e-6 (less clumsy than e.g.<br>
> > > asUsefulApproximateFraction).<br>
> > ><br>
> > > _,,,^..^,,,_<br>
> > > best, Eliot<br>
> ><br>
> > ><br>
> ><br>
> ><br>
> ><br>
> <br>
> <br>
> -- <br>
> _,,,^..^,,,_<br>
> best, Eliot<br>
<br>
> <br>
<br>
<br>
</div></div></blockquote></div><br></div>