📄 xftoa.c
字号:
double mant; /* mantissa */
int jexp;
extern double frexp(double, int *);
extern int _ltoa(long value, char *string);
union {
double dbl;
struct {
#if defined (_LITTLE_ENDIAN) || defined (__i960_BIG_ENDIAN__)
unsigned long lo, hi;
#else
unsigned long hi, lo;
#endif
} lng;
} cracker;
cracker.dbl = value; /* prepare to break it apart */
if ((cracker.lng.hi & 0x7ff00000) == 0x7ff00000)/* inf or nan ?? */
{
if ((cracker.lng.hi & 0x000fffff) || cracker.lng.lo) /* NaN*/
{
strcpy (buf, nan);
count = sizeof (nan);
}
else
{
count = 0; /* preset */
if (cracker.lng.hi & 0x80000000) /* neg. inf. */
{
*buf++ = '-';
count++;
}
strcpy (buf, infinity);
count += sizeof (infinity);
}
return --count;
}
negAlt = 1; /* alt fmt == false */
if (fmt & 0x80) /* check sign bit in fmt */
{
negAlt = 0; /* alt fmt == true */
fmt &= 0x7f; /* correct fmt */
}
count = 0;
f_fmt = g_fmt = 0; /* assume e format */
iszero = 0;
if (prec < 0)
prec = 6;
if (fmt == 'g' || fmt == 'G') {
g_fmt = 1;
if (prec == 0) ++prec;
}
else {
++prec;
if (fmt == 'f') f_fmt = 1;
}
xprec = prec;
if (xprec > MAXSIG) /* no significance if too big */
xprec = MAXSIG;
if (value < 0.0) { /* take care of negative number */
*buf++ = '-';
count++;
value = -value;
}
/* split value into mantissa and exponent */
mant = value;
if (IS_ZERO (mant)) /* check for zero */
{ iexp = 0; iszero = 1; }
else {
/*
* want to compute exponent as 10 ** EXP
* frexp() returns exponent as 2 ** jexp
* EXP = jexp * log10(2)
* Note: frexp() is fast - no FP involved
*/
(void) frexp(mant,&jexp);
jexp = (int)(jexp * 308L) >> 10; /* 308/1024 ~= log10(2) */
negexp = 0;
if ((iexp = jexp) < 0) {
jexp = -jexp;
negexp++;
}
for (i = 0; jexp != 0; i++) {
if (jexp & 1) {
if (negexp)
mant *= pow10[i];
else
mant /= pow10[i];
}
jexp = (unsigned)jexp >> 1;
}
if (mant < 1.0)
{ iexp--; mant *= 10.0; }
else if (mant >= 10.0)
{ iexp++; mant /= 10.0; }
}
if (g_fmt && iexp >= -4 && iexp < prec)
f_fmt = 1; /* use f format */
p = buf;
buf0 = p;
if (iszero) /* value == 0.0 */
*p++ = '0';
else { /* do integer part */
i = 1;
if (! f_fmt)
value = mant;
else if ((i = iexp) < 0)
i = 1;
for (j = i; j >= 9; j -= 9)
value /= 1E9; /* scale down if > 2^63 - 1 */
for (grp = 0; grp < 3; ++grp) {
lval = (long) value; /* convert to long */
if (grp != 0)
for (k=0; lval < ltab[k]; ++k)
*p++ = '0';
if (lval != 0L) {
p += _ltoa(lval,p); /* up to 9 digits at a time */
value -= (double) lval;
}
if ((i -= j) == 0)
break;
j = 9;
if (grp < 2)
value *= 1E9; /* scale up for next 9 digits */
}
if (f_fmt) {
if (iexp > MAXSIG)
for (p0 = buf0+MAXSIG; p0 < p; p0++)
*p0 = '0'; /* no more sigificance */
if (iexp < 0)
i = 1;
for ( ; --i >= 0; )
*p++ = '0'; /* just fill with zeros */
if (iexp + xprec >= MAXSIG)
if ((xprec = MAXSIG-iexp) <= 0)
xprec = iszero = 1; /* all zeros after decpt */
}
}
decpt = p;
*p++ = '.';
if (iszero) /* value == 0.0 */
for (i = prec; --i != 0; )
*p++ = '0';
else { /* do fraction part */
if (f_fmt && iexp < 0) {
value = mant / 10.0;
for (i = iexp; ++i != 0; )
*p++ = '0'; /* leading zeros in fraction */
}
for (i = 0; i < 2; i++) { /* do twice (up to 18 digits) */
if (value == 0.0) {
for (j = 9; --j >= 0; )
*p++ = '0';
continue;
}
value *= 1E9; /* 9 digits at a time */
lval = (long) value;
for (k=0; lval < ltab[k]; ++k)
*p++ = '0';
p += _ltoa(lval,p);
if (prec <= 9)
break;
if (i == 0)
value -= (double) lval;
}
if (g_fmt && f_fmt) /* fixup for g format */
xprec += -iexp;
for (p0=decpt+xprec+1; p0 < p; p0++)
*p0 = '0';
}
*p = '\0';
/* Now, round-off and truncate */
if (g_fmt) {
if (xprec > prec) /* due to leading zeros */
prec = xprec;
if ((p0 = buf0 + prec) >= decpt) p0++;
if (p < p0) p0 = p;
}
else {
p0 = decpt + prec;
while (p <= p0) /* precision > fractional digits */
*p++ = '0';
}
p = round = decpt + xprec;
if (*p >= '5') {
while (1) { /* round preceeding digit */
if (*--p == '.') --p;
if ((*p += 1) <= '9') break;
*p = '0';
if (p == buf) { /* round highest digit -- so shift */
register char * tempPnt;
++p0; /* bump pointers */
++round;
for (tempPnt = round; tempPnt != p; --tempPnt)/* shift */
*tempPnt = *(tempPnt-1);
*p = '1'; /* complete the round */
buf0 = p;
if (! f_fmt) {
*++p = '.'; /* change 10.*** to 1.0*** */
*++p = '0';
iexp++; /* add 1 to exponent */
--p0;
}
break;
}
}
}
*round = '0'; /* the digit being rounded */
*p0 = '\0'; /* ends the string */
p = p0;
if (g_fmt) {
fmt += 'e' - 'g';
if (negAlt) {
while (*--p == '0') /* strip trailing zeros */
;
*++p = '\0';
}
}
if ((*(p-1) == '.') && negAlt) /* no digit after decimal pt ? */
*--p = '\0'; /* strip '.' */
if (! f_fmt) { /* do exponent part */
*p++ = fmt; /* 'e' or 'E' */
if (iexp >= 0)
*p++ = '+';
else {
*p++ = '-';
iexp = -iexp;
}
if ((i = iexp) > 99) { /* need 3 digits */
*p++ = i / 100 + '0';
i %= 100;
}
*p++ = i / 10 + '0';
*p++ = i % 10 + '0';
*p = '\0';
}
i = (int) ((DIFF)p - (DIFF)buf0);
return (count + i);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -