📄 floatlib.c
字号:
* reverse integer into beginning of buffer, * note, decrement precision */ if (expcnt) for (; ++p < endp; *t++ = *p, --prec) ; else *t++ = '0'; /* * if precision required or alternate flag set, add in a * decimal point. If no digits yet, add in leading 0. */ if (prec || doAlt) { dotrim = 1; *t++ = '.'; } else dotrim = 0; /* if requires more precision and some fraction left */ if (fract) { if (prec) { /* * If there is a zero integer portion, so we can't count any * of the leading zeros as significant. Roll 'em on out until * we get to the first non-zero one. */ if (!nonZeroInt) { do { fract = modf(fract * 10, &tmp); *t++ = to_char((int)tmp); } while(!tmp); prec--; } /* * Now add on a number of digits equal to our precision. */ while (prec && fract) { fract = modf(fract * 10, &tmp); *t++ = to_char((int)tmp); prec--; } } if (fract) startp = roundCvt (fract, (int *)NULL, startp, t - 1, (char)0, pDoSign); } /* alternate format, adds 0's for precision, else trim 0's */ if (doAlt) for (; prec--; *t++ = '0') ; else if (dotrim) { while (t > startp && *--t == '0') ; if (*t != '.') ++t; } default : break; } return (t - startp); }/******************************************************************************** roundCvt - helper function for floatFormat* * RETURNS: */LOCAL char *roundCvt ( double fract, int * exp, FAST char * start, FAST char * end, char ch, BOOL * pDoSign ) { double tmp; if (fract) (void)modf(fract * 10, &tmp); else tmp = to_digit(ch); if (tmp > 4) { for (;; --end) { if (*end == '.') --end; if (++*end <= '9') break; *end = '0'; if (end == start) { if (exp) { /* e/E; increment exponent */ *end = '1'; ++*exp; } else { /* f; add extra digit */ *--end = '1'; --start; } break; } } } /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ else if (*pDoSign) for (;; --end) { if (*end == '.') --end; if (*end != '0') break; if (end == start) *pDoSign = FALSE; } return (start); }/******************************************************************************** exponentCvt - helper function for floatFormat* * RETURNS: */LOCAL char *exponentCvt ( FAST char * p, FAST int exp, int fmtch ) { FAST char *t; char expbuf[MAXEXP]; *p++ = fmtch; if (exp < 0) { exp = -exp; *p++ = '-'; } else *p++ = '+'; t = expbuf + MAXEXP; if (exp > 9) { do { *--t = to_char(exp % 10); } while ((exp /= 10) > 9); *--t = to_char(exp); for (; t < expbuf + MAXEXP; *p++ = *t++) ; } else { *p++ = '0'; *p++ = to_char(exp); } return (p); }/********************************************************************************* floatScan - scan ASCII input to a floating-point number** This routine scans the ASCII input into a floating-point number.** [+-]<digs>.<digs>e[+-]<digs>** RETURNS: TRUE if successful, FALSE if unsuccessful*/LOCAL BOOL floatScan ( FAST int * pReturn, int returnSpec, /* 0, 'l', 'L' */ int fieldwidth, FAST FUNCPTR getRtn, FAST int getArg, int * pCh, int * pNchars ) {#define DBL_DIG 16 /* float.h */#define GET_CHAR(ch, ix) ((ix)++, (ch) = getRtn (getArg)) static double power10 [] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8}; static double posExpPower10 [] = {1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128, 1e256, 0}; FAST int ch = *pCh; /* current char */ FAST int ix = 0; /* number of chars consumed */ FAST long long1 = 0; /* 1st part of integer representation */ FAST long long2 = 0; /* 2nd part of integer representation */ int ndigs1 = 0; /* num of digits in long1 */ int ndigs2 = 0; /* num of digits in long2 */ int ndigsPrec = 0; /* num of digits of precision total */ BOOL fracPart = FALSE; /* TRUE = doing digits after '.' */ int ndigsFrac = 0; /* number of digits after '.' */ int exp = 0; /* exponent */ double num; /* double representation of number */ BOOL negnum = FALSE; /* number is negative */ BOOL negexp = FALSE; /* exponent is negative */ double * pExpPower10; /* current exponent bit multiplier */ /* check for sign */ if (ix < fieldwidth) { if ((negnum = ((char)ch == '-')) || ((char)ch == '+')) GET_CHAR (ch, ix); } /* scan integer and fraction parts */ for (; (ch != EOF) && (ix < fieldwidth); GET_CHAR (ch, ix)) { if (!fracPart && ch == '.') { fracPart = TRUE; continue; } if ((ch < '0') || (ch > '9')) break; ch -= '0'; /* turn ch into digit */ if (fracPart) /* count digits after '.' */ ndigsFrac++; if ((ndigsPrec != 0) || (ch != 0)) /* skip leading 0s */ { ndigsPrec++; /* check if another digit will fit in long1 */ if (long1 < ((INT_MAX - 9) / 10)) { long1 = 10 * long1 + ch; ndigs1++; } else if (ndigsPrec <= DBL_DIG) { long2 = 10 * long2 + ch; ndigs2++; } } } /* scan for explicit exponent */ if ((ix < fieldwidth) && (ch == 'e' || ch == 'E')) { GET_CHAR (ch, ix); /* skip over sign */ if (ix < fieldwidth) { if ((negexp = (ch == '-')) || (ch == '+')) GET_CHAR (ch, ix); } for (; (ch != EOF) && (ix < fieldwidth); GET_CHAR (ch, ix)) { if ((ch < '0') || (ch > '9')) break; exp = 10 * exp + (ch - '0'); } } /* check that we scanned at least one character */ if (ix == 0) return (FALSE); /* put significant digits into double representation */ num = long1; if (ndigs2 != 0) num = num * power10 [ndigs2] + long2; /* apply exponent to number; total effective exponent = * + number of digits of precision that were scanned but not * represented in the number (ndigsPrec - ndigs1 - ndigs2) * - number of digits scanned after the '.' (ndigsFrac) * + the scanned explicit exponent */ exp = (ndigsPrec - ndigs1 - ndigs2) - ndigsFrac + (negexp ? -exp : exp); if ((negexp = (exp < 0))) exp = -exp; pExpPower10 = posExpPower10; while ((exp != 0) && (*pExpPower10 != 0)) { if (exp & 1) { if (negexp) num /= *pExpPower10; else num *= *pExpPower10; } exp >>= 1; pExpPower10++; } if (exp != 0) { /* exponent too big */ if (negexp) num = 0; else { /* Infinity */ ((DOUBLE *) &num)->ldat.l1 = 0x7ff00000; ((DOUBLE *) &num)->ldat.l2 = 0; } } /* return value to caller */ if (negnum) num = -num; if (pReturn != NULL) { switch (returnSpec) { case 'l': * (double *) pReturn = num; break; default: * (float *) pReturn = num; break; } } *pCh = ch; *pNchars += ix; return (ix != 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -