formatter . , %g (e20 e+020: 2 ), :
:
void encode(double f, char *buf) {
char line[40];
char format[8];
int prec;
int l;
l = sprintf(line, "%.17g", f);
if (l > 16) {
prec = 33 - strlen(line);
l = sprintf(line, "%.*g", prec, f);
while(l > 16) {
prec -=1;
l = sprintf(line, "%.*g", prec, f);
}
}
strcpy(buf, line);
}
( e30 e + 030), % 1.16e . ( ):
%1.16e ( 10)- -2 () ():
- 0 -2 ( ): .
- -1 -3 ( ): ,
0 - else
e
:
- ,
- -1 - :
>=5, , 9. 9.9999999999... , 10
:
void clean(char *mant) {
char *ix = mant + strlen(mant) - 1;
while(('0' == *ix) && (ix > mant)) {
*ix-- = '\0';
}
if ('.' == *ix) {
*ix = '\0';
}
}
int add1(char *buf, int n) {
if (n < 0) return 1;
if (buf[n] == '9') {
buf[n] = '0';
return add1(buf, n-1);
}
else {
buf[n] += 1;
}
return 0;
}
int doround(char *buf, unsigned int n) {
char c;
if (n >= strlen(buf)) return 0;
c = buf[n];
buf[n] = 0;
if ((c >= '5') && (c <= '9')) return add1(buf, n-1);
return 0;
}
int roundat(char *buf, unsigned int i, int iexp) {
if (doround(buf, i) != 0) {
iexp += 1;
switch(iexp) {
case -2:
strcpy(buf, ".01");
break;
case -1:
strcpy(buf, ".1");
break;
case 0:
strcpy(buf, "1.");
break;
case 1:
strcpy(buf, "10");
break;
case 2:
strcpy(buf, "100");
break;
default:
sprintf(buf, "1e%d", iexp);
}
return 1;
}
return 0;
}
void encode(double f, char *buf, int size) {
char line[40];
char *mant = line + 1;
int iexp, lexp, i;
char exp[6];
if (f < 0) {
f = -f;
size -= 1;
*buf++ = '-';
}
sprintf(line, "%1.16e", f);
if (line[0] == '-') {
f = -f;
size -= 1;
*buf++ = '-';
sprintf(line, "%1.16e", f);
}
*mant = line[0];
i = strcspn(mant, "eE");
mant[i] = '\0';
iexp = strtol(mant + i + 1, NULL, 10);
lexp = sprintf(exp, "e%d", iexp);
if ((iexp >= size) || (iexp < -3)) {
i = roundat(mant, size - 1 -lexp, iexp);
if(i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = mant[0];
buf[1] = '.';
strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
buf[size-lexp] = 0;
clean(buf);
strcat(buf, exp);
}
else if (iexp >= size - 2) {
roundat(mant, iexp + 1, iexp);
strcpy(buf, mant);
}
else if (iexp >= 0) {
i = roundat(mant, size - 1, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
strncpy(buf, mant, iexp + 1);
buf[iexp + 1] = '.';
strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
buf[size] = 0;
clean(buf);
}
else {
int j;
i = roundat(mant, size + 1 + iexp, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = '.';
for(j=0; j< -1 - iexp; j++) {
buf[j+1] = '0';
}
if ((i == 1) && (iexp != -1)) {
buf[-iexp] = '1';
buf++;
}
strncpy(buf - iexp, mant, size + 1 + iexp);
buf[size] = 0;
clean(buf);
}
}