Re: Bug in srfi-48?

Shiro Kawai <[email protected]> Fri, 13 Oct 2017 09:54:51 -1000
Newsgroups gmane.lisp.scheme.srfi.srfi-48
Message-ID <CALN0JNHuA1aYUcHUVQmn5owGZ4v8K=MLADbWVmb9sMyB1z3iTA@mail.gmail.com>
--001a1134f460b3d4f0055b730702
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-SL-Modified: truncated_text

"Scale by 10^d and round" scheme works mostly, and I use it often when the
rare case doesn't matter.
I vaguely remember there're fail cases due to double rounding (scaling by
10^d requires more bits than
the original number, causing the spilled bits to be rounded by
floating-point calculation, and in rare cases,
that rounding crosses over the midpoint of our rounding).   I couldn't find
the actual case now, though.


On Fri, Oct 13, 2017 at 7:52 AM, Donald Allen <[email protected]>
wrote:

> On 13 October 2017 at 13:51, Marc Feeley <[email protected]> wrote:
> > I=E2=80=99ve found this code works well for me=E2=80=A6
> >
> > (define (num->string num w d) ; w =3D total width, d =3D decimals
> >  (let ((n (round (* (abs (inexact->exact num)) (expt 10 d)))))
> >    (let ((i (quotient n (expt 10 d)))
> >          (f (modulo n (expt 10 d))))
> >      (let ((si (string-append
> >                  (if (< num 0) "-" "")
> >                  (number->string i 10)))
> >            (sf (if (> d 0)
> >                    (let ((sf (number->string (+ f (expt 10 d)) 10)))
> >                      (string-set! sf 0 #\.)
> >                      sf)
> >                    "")))
> >        (let ((lsi (string-length si))
> >              (lsf (string-length sf)))
> >          (let ((blanks (- w (+ lsi lsf))))
> >            (string-append (make-string (max blanks 0) #\space) si
> sf)))))))
> >
> > Perhaps that=E2=80=99s better for your purpose than srfi-48.
>
> Thank you. I will give it a try.
>
> /Don
>

--001a1134f460b3d4f0055b730702
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-SL-Modified: truncated_html

<div dir=3D"ltr">&quot;Scale by 10^d and round&quot; scheme works mostly, a=
nd I use it often when the rare case doesn&#39;t matter.<div>I vaguely reme=
mber there&#39;re fail cases due to double rounding (scaling by 10^d requir=
es more bits than</div><div>the original number, causing the spilled bits t=
o be rounded by floating-point calculation, and in rare cases,</div><div>th=
at rounding crosses over the midpoint of our rounding).=C2=A0 =C2=A0I could=
n&#39;t find the actual case now, though.</div><div><br></div></div><div cl=
ass=3D"gmail_extra"><br><div class=3D"gmail_quote">On Fri, Oct 13, 2017 at =
7:52 AM, Donald Allen <span dir=3D"ltr">&lt;<a href=3D"mailto:donaldcallen@=
gmail.com" target=3D"_blank">[email protected]</a>&gt;</span> wrote:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><span class=3D"">On 13 October 2017 at 13:=
51, Marc Feeley &lt;<a href=3D"mailto:[email protected]">[email protected]=
montreal.ca</a>&gt; wrote:<br>
&gt; I=E2=80=99ve found this code works well for me=E2=80=A6<br>
&gt;<br>
&gt; (define (num-&gt;string num w d) ; w =3D total width, d =3D decimals<b=
r>
&gt;=C2=A0 (let ((n (round (* (abs (inexact-&gt;exact num)) (expt 10 d)))))=
<br>
&gt;=C2=A0 =C2=A0 (let ((i (quotient n (expt 10 d)))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (f (modulo n (expt 10 d))))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 (let ((si (string-append<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if (&lt=
; num 0) &quot;-&quot; &quot;&quot;)<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (number-=
&gt;string i 10)))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (sf (if (&gt; d 0)<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (=
let ((sf (number-&gt;string (+ f (expt 10 d)) 10)))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 (string-set! sf 0 #\.)<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 sf)<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &=
quot;&quot;)))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((lsi (string-length si))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lsf (string-length sf=
)))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((blanks (- w (+ lsi lsf))))<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (string-append (make-string (=
max blanks 0) #\space) si sf)))))))<br>
&gt;<br>
&gt; Perhaps that=E2=80=99s better for your purpose than srfi-48.<br>
<br>
</span>Thank you. I will give it a try.<br>
<br>
/Don<br>
</blockquote></div><br></div>

--001a1134f460b3d4f0055b730702--