⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fltfmt.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <float.h>#include <ctype.h>#include "fmtdef.h"enum{	FDIGIT	= 30,	FDEFLT	= 6,	NSIGNIF	= 17};/* * first few powers of 10, enough for about 1/2 of the * total space for doubles. */static double pows10[] ={	  1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,   1e9,  	 1e10,  1e11,  1e12,  1e13,  1e14,  1e15,  1e16,  1e17,  1e18,  1e19,  	 1e20,  1e21,  1e22,  1e23,  1e24,  1e25,  1e26,  1e27,  1e28,  1e29,  	 1e30,  1e31,  1e32,  1e33,  1e34,  1e35,  1e36,  1e37,  1e38,  1e39,  	 1e40,  1e41,  1e42,  1e43,  1e44,  1e45,  1e46,  1e47,  1e48,  1e49,  	 1e50,  1e51,  1e52,  1e53,  1e54,  1e55,  1e56,  1e57,  1e58,  1e59,  	 1e60,  1e61,  1e62,  1e63,  1e64,  1e65,  1e66,  1e67,  1e68,  1e69,  	 1e70,  1e71,  1e72,  1e73,  1e74,  1e75,  1e76,  1e77,  1e78,  1e79,  	 1e80,  1e81,  1e82,  1e83,  1e84,  1e85,  1e86,  1e87,  1e88,  1e89,  	 1e90,  1e91,  1e92,  1e93,  1e94,  1e95,  1e96,  1e97,  1e98,  1e99,  	1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, 	1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 	1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 	1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 	1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 	1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, };#undef pow10#define  pow10(x)  fmtpow10(x)static doublepow10(int n){	double d;	int neg;	neg = 0;	if(n < 0){		if(n < DBL_MIN_10_EXP){			return 0.;		}		neg = 1;		n = -n;	}else if(n > DBL_MAX_10_EXP){		return HUGE_VAL;	}	if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))		d = pows10[n];	else{		d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];		for(;;){			n -= sizeof(pows10)/sizeof(pows10[0]) - 1;			if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){				d *= pows10[n];				break;			}			d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];		}	}	if(neg){		return 1./d;	}	return d;}static intxadd(char *a, int n, int v){	char *b;	int c;	if(n < 0 || n >= NSIGNIF)		return 0;	for(b = a+n; b >= a; b--) {		c = *b + v;		if(c <= '9') {			*b = c;			return 0;		}		*b = '0';		v = 1;	}	*a = '1';	/* overflow adding */	return 1;}static intxsub(char *a, int n, int v){	char *b;	int c;	for(b = a+n; b >= a; b--) {		c = *b - v;		if(c >= '0') {			*b = c;			return 0;		}		*b = '9';		v = 1;	}	*a = '9';	/* underflow subtracting */	return 1;}static voidxdtoa(Fmt *fmt, char *s2, double f){	char s1[NSIGNIF+10];	double g, h;	int e, d, i, n;	int c1, c2, c3, c4, ucase, sign, chr, prec;	prec = FDEFLT;	if(fmt->flags & FmtPrec)		prec = fmt->prec;	if(prec > FDIGIT)		prec = FDIGIT;	if(__isNaN(f)) {		strcpy(s2, "NaN");		return;	}	if(__isInf(f, 1)) {		strcpy(s2, "+Inf");		return;	}	if(__isInf(f, -1)) {		strcpy(s2, "-Inf");		return;	}	sign = 0;	if(f < 0) {		f = -f;		sign++;	}	ucase = 0;	chr = fmt->r;	if(isupper(chr)) {		ucase = 1;		chr = tolower(chr);	}	e = 0;	g = f;	if(g != 0) {		frexp(f, &e);		e = e * .301029995664;		if(e >= -150 && e <= +150) {			d = 0;			h = f;		} else {			d = e/2;			h = f * pow10(-d);		}		g = h * pow10(d-e);		while(g < 1) {			e--;			g = h * pow10(d-e);		}		while(g >= 10) {			e++;			g = h * pow10(d-e);		}	}	/*	 * convert NSIGNIF digits and convert	 * back to get accuracy.	 */	for(i=0; i<NSIGNIF; i++) {		d = g;		s1[i] = d + '0';		g = (g - d) * 10;	}	s1[i] = 0;	/*	 * try decimal rounding to eliminate 9s	 */	c2 = prec + 1;	if(chr == 'f')		c2 += e;	if(c2 >= NSIGNIF-2) {		strcpy(s2, s1);		d = e;		s1[NSIGNIF-2] = '0';		s1[NSIGNIF-1] = '0';		sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);		g = strtod(s1, nil);		if(g == f)			goto found;		if(xadd(s1, NSIGNIF-3, 1)) {			e++;			sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);		}		g = strtod(s1, nil);		if(g == f)			goto found;		strcpy(s1, s2);		e = d;	}	/*	 * convert back so s1 gets exact answer	 */	for(;;) {		sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);		g = strtod(s1, nil);		if(f > g) {			if(xadd(s1, NSIGNIF-1, 1))				e--;			continue;		}		if(f < g) {			if(xsub(s1, NSIGNIF-1, 1))				e++;			continue;		}		break;	}found:	/*	 * sign	 */	d = 0;	i = 0;	if(sign)		s2[d++] = '-';	else if(fmt->flags & FmtSign)		s2[d++] = '+';	else if(fmt->flags & FmtSpace)		s2[d++] = ' ';	/*	 * copy into final place	 * c1 digits of leading '0'	 * c2 digits from conversion	 * c3 digits of trailing '0'	 * c4 digits after '.'	 */	c1 = 0;	c2 = prec + 1;	c3 = 0;	c4 = prec;	switch(chr) {	default:		if(xadd(s1, c2, 5))			e++;		break;	case 'g':		/*		 * decide on 'e' of 'f' style convers		 */		if(xadd(s1, c2, 5))			e++;		if(e >= -5 && e <= prec) {			c1 = -e - 1;			c4 = prec - e;			chr = 'h';	// flag for 'f' style		}		break;	case 'f':		if(xadd(s1, c2+e, 5))			e++;		c1 = -e;		if(c1 > prec)			c1 = c2;		c2 += e;		break;	}	/*	 * clean up c1 c2 and c3	 */	if(c1 < 0)		c1 = 0;	if(c2 < 0)		c2 = 0;	if(c2 > NSIGNIF) {		c3 = c2-NSIGNIF;		c2 = NSIGNIF;	}	/*	 * copy digits	 */	while(c1 > 0) {		if(c1+c2+c3 == c4)			s2[d++] = '.';		s2[d++] = '0';		c1--;	}	while(c2 > 0) {		if(c2+c3 == c4)			s2[d++] = '.';		s2[d++] = s1[i++];		c2--;	}	while(c3 > 0) {		if(c3 == c4)			s2[d++] = '.';		s2[d++] = '0';		c3--;	}	/*	 * strip trailing '0' on g conv	 */	if(fmt->flags & FmtSharp) {		if(0 == c4)			s2[d++] = '.';	} else	if(chr == 'g' || chr == 'h') {		for(n=d-1; n>=0; n--)			if(s2[n] != '0')				break;		for(i=n; i>=0; i--)			if(s2[i] == '.') {				d = n;				if(i != n)					d++;				break;			}	}	if(chr == 'e' || chr == 'g') {		if(ucase)			s2[d++] = 'E';		else			s2[d++] = 'e';		c1 = e;		if(c1 < 0) {			s2[d++] = '-';			c1 = -c1;		} else			s2[d++] = '+';		if(c1 >= 100) {			s2[d++] = c1/100 + '0';			c1 = c1%100;		}		s2[d++] = c1/10 + '0';		s2[d++] = c1%10 + '0';	}	s2[d] = 0;}static intfloatfmt(Fmt *fmt, double f){	char s[341];		/* precision+exponent+sign+'.'+null */	xdtoa(fmt, s, f);	fmt->flags &= FmtWidth|FmtLeft;	__fmtcpy(fmt, s, strlen(s), strlen(s));	return 0;}int__efgfmt(Fmt *f){	double d;	d = va_arg(f->args, double);	return floatfmt(f, d);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -