#include #include #include /* convert double to string. Helper for sprintf. */ static int copystring(char* buf,int maxlen, const char* s) { int i; for (i=0; i<3&&i>52)&((1<<11)-1))-1023; #else #if __BYTE_ORDER == __LITTLE_ENDIAN signed long e=(((((unsigned long*)&d)[1])>>20)&((1<<11)-1))-1023; #else signed long e=(((*((unsigned long*)&d))>>20)&((1<<11)-1))-1023; #endif #endif /* unsigned long long m=u.l & ((1ull<<52)-1); */ /* step 2: exponent is base 2, compute exponent for base 10 */ signed long e10; /* step 3: calculate 10^e10 */ unsigned int i; double backup=d; double tmp; char *oldbuf=buf; if ((i=isinf(d))) return copystring(buf,maxlen,i>0?"inf":"-inf"); if (isnan(d)) return copystring(buf,maxlen,"nan"); e10=1+(long)(e*0.30102999566398119802); /* log10(2) */ /* Wir iterieren von Links bis wir bei 0 sind oder maxlen erreicht * ist. Wenn maxlen erreicht ist, machen wir das nochmal in * scientific notation. Wenn dann von prec noch was übrig ist, geben * wir einen Dezimalpunkt aus und geben prec2 Nachkommastellen aus. * Wenn prec2 Null ist, geben wir so viel Stellen aus, wie von prec * noch übrig ist. */ if (d==0.0) { prec2=prec2==0?1:prec2+2; prec2=prec2>maxlen?8:prec2; i=0; if (prec2 && (long long)u.l<0) { buf[0]='-'; ++i; } for (; i0) { int first=1; /* are we about to write the first digit? */ tmp = 10.0; i=e10; while (i>10) { tmp=tmp*1e10; i-=10; } while (i>1) { tmp=tmp*10; --i; } /* the number is greater than 1. Iterate through digits before the * decimal point until we reach the decimal point or maxlen is * reached (in which case we switch to scientific notation). */ while (tmp>0.9) { char digit; double fraction=d/tmp; digit=(int)(fraction); /* floor() */ if (!first || digit) { first=0; *buf=digit+'0'; ++buf; if (!maxlen) { /* use scientific notation */ int len=__dtostr(backup/tmp,oldbuf,maxlen,prec,prec2,0); int initial=1; if (len==0) return 0; maxlen-=len; buf+=len; if (maxlen>0) { *buf='e'; ++buf; } --maxlen; for (len=1000; len>0; len/=10) { if (e10>=len || !initial) { if (maxlen>0) { *buf=(e10/len)+'0'; ++buf; } --maxlen; initial=0; e10=e10%len; } } if (maxlen>0) goto fini; return 0; } d-=digit*tmp; --maxlen; } tmp/=10.0; } } else { tmp = 0.1; } if (buf==oldbuf) { if (!maxlen) return 0; --maxlen; *buf='0'; ++buf; } if (prec2 || prec>(unsigned int)(buf-oldbuf)+1) { /* more digits wanted */ if (!maxlen) return 0; --maxlen; *buf='.'; ++buf; if (g) { if (prec2) prec=prec2; prec-=buf-oldbuf-1; } else { prec-=buf-oldbuf-1; if (prec2) prec=prec2; } if (prec>maxlen) return 0; while (prec>0) { char digit; double fraction=d/tmp; digit=(int)(fraction); /* floor() */ *buf=digit+'0'; ++buf; d-=digit*tmp; tmp/=10.0; --prec; } } fini: *buf=0; return buf-oldbuf; }