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

📄 fltfmt.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <ctype.h>#include "fmtdef.h"enum{	FDIGIT	= 30,	FDEFLT	= 6,	NSIGNIF	= 17,	NEXP10	= 308,};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;}int_floatfmt(Fmt *fmt, double f){	char s[1+NEXP10+1+FDIGIT+1];	/*	 * The max length of a %f string is	 *	'[+-]'+"max exponent"+'.'+"max precision"+'\0'	 * which is 341 currently.	 */		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 + -