Greetings! Raymond Toy <toy.raym...@gmail.com> writes:
>>>>>> "Camm" == Camm Maguire <c...@maguirefamily.org> writes: > > Camm> Greetings! > Camm> Raymond Toy <toy.raym...@gmail.com> writes: > > >>>>>>> "Camm" == Camm Maguire <c...@maguirefamily.org> writes: > >> > Camm> Greetings! > Camm> "Stewart W. Wilson" <wil...@prediction-dynamics.com> writes: > >> > >> >> The fix does not seem to be exactly trivial. Please see the > attached > >> >> paper by Steele and White from 1990. > >> >> > >> > Camm> Thanks so much for this reference! > >> > Camm> Unfortunately, using up to forty 32bit words in bignum arithmetic to > Camm> print out floats looks prohibitively expensive, although the > algorithm > Camm> does appear to work nicely, at least when coded in lisp. > >> > >> FWIW, cmucl has a lisp implementation of Dybvig's float printer. > >> Perhaps that will work for you? > >> > > Camm> It might very well. But is there anything objectionable to a loop > over > Camm> strtod when printing? Even in corner cases, it appears very fast. > > It seems so random. What happens if strtod prints out xxx...99999 > when the "true" answer is xxxy...0000? And the corner cases might not > be what you think are corner cases. For example, see > http://trac.common-lisp.net/cmucl/ticket/1. > Well, strtod takes a string and gives a double, without malloc it appears (as makes sense). This would seem to be an unambiguous mapping with a definitive algorithm, but of course bugs are always possible. The key loop in the just committed implementation is: static int char_inc(char *b,char *p) { if (b==p) { if (*p=='-') { p++; memmove(p+1,p,strlen(p)+1); } *p='1'; } else if (*p=='9') { *p='0'; char_inc(b,p-1); } else if (*p=='.') char_inc(b,p-1); else (*p)++; return 1; } #define COMP(a_,b_,c_,d_) ((d_) ? strtod((a_),(b_))==(c_) : strtof((a_),(b_))==(float)(c_)) static int truncate_double(char *b,double d,int dp) { char c[FPRC+9],c1[FPRC+9],*p,*pp,*n; int j,k; n=b; k=strlen(n); strcpy(c1,b); for (p=c1;*p && *p!='e';p++); pp=p>c1 && p[-1]!='.' ? p-1 : p; for (;pp>c1 && pp[-1]=='0';pp--); strcpy(pp,p); if (pp!=p && COMP(c1,&pp,d,dp)) k=truncate_double(n=c1,d,dp); strcpy(c,n); for (p=c;*p && *p!='e';p++); if (p[-1]!='.' && char_inc(c,p-1) && COMP(c,&pp,d,dp)) { j=truncate_double(c,d,dp); if (j<k) { k=j; n=c; } } if (n!=b) strcpy(b,n); return k; } > At least with the lisp code you have a provably correct algorithm > guaranteed to produce the correct answer. (Barring bugs in > implementation, of course!) > I'd like to look at this as an improvement at some point. But I do think controlling allocations will be critical, which at least was not straightforward when I implemented in lisp the algorithm described in the originally submitted paper. Take care, > Ray > > > _______________________________________________ > Gcl-devel mailing list > Gcl-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/gcl-devel > > > > -- Camm Maguire c...@maguirefamily.org ========================================================================== "The earth is but one country, and mankind its citizens." -- Baha'u'llah _______________________________________________ Gcl-devel mailing list Gcl-devel@gnu.org https://lists.gnu.org/mailman/listinfo/gcl-devel