我遇到了fprintf的问题。我想要的是使用尽可能多的空间停留在同一列,但这意味着改变十进制浮点数的数量。我有点问题要描述它,所以也许只是例子:
0.001234
0.123456
1.234567
12.34567
123.4567
我尝试使用g和f选项,但它对我不起作用(例如%8.6g
或%8.6f
)。
答案 0 :(得分:3)
这对于幸存的角落来说是个棘手的问题。
使用不同的精度说明符时,小数点左侧的位数会发生变化。
printf("%.3f", 9.996) --> "9.996";
printf("%.2f", 9.996) --> "10.00"; // Same print width with different precision.
给定各种舍入模式,+ / - 数字,NaN,INF和浮点数的典型二进制表示的细节,尝试预测给定浮点数的宽度printf()
,at最好的,近似的。而不是超出思考printf()
,简单sprintf()
具有最佳猜测精度。使用sprintf()
返回值并根据需要调整精度。
解决方案:
#include <float.h>
int fprintf_Width(FILE *outf, double a, int width) {
// Subtract 2 for a potential leading "0."
int prec = width - 2;
if (prec < 0 || prec > 100 /* TBD upper bound */)
return 0; // `width` out of range
// By some means, determine the approximate precision needed.
char buf[1 + 1 + DBL_MAX_10_EXP + 1 + prec + 1];
int len = sprintf(buf, "%#.*f", prec, a);
prec -= len - width;
if (prec < 0)
return 0; // `a` too big
// Try it out
len = sprintf(buf, "%#.*f", prec, a);
// Adjust as needed
if (len > width) {
prec--;
if (prec < 0)
return 0; // `a` too big
sprintf(buf, "%#.*f", prec, a);
}
len = fprintf(outf, "%s", buf);
return len;
}
答案 1 :(得分:0)
鸣谢:正如评论中所指出的,这种方法会因某些宽度规格的数字而失败。
您可以做的一件事是计算小数点前的位数,然后使用printf
Precision Specification截断会使数字太长的数字。
您可以创建一个自定义函数,将FILE
指针用于要打印的fprintf
,float
nubmer以及您想要的所需字符数量有; 3个论点。
接下来要做的是确定小数点前的位数。拥有一个新的int
变量并将float
放入其中,然后将新的int
除以10
,直到它为零,就应该这样做。但请注意,0.001234
在小数点前也有一位数,但int
评估不会显示一位数。
然后你所要做的就是减少小数点前的数字位数,加上小数点本身的1(或者更确切地说是负数),这应该是您将使用的fprintf
精度规格。
所以,最后,您的fprintf
应该看起来像这样:
fprintf( fp, "%.*f", Width - digitsbeforeDpoint - 1 );
这是我已经完成的一个例子,我可以测试。它还有一些进一步的预防措施,确保每个输入都是合理的,并确保给定的浮点数有资格打印出你想要的数字位数:
#include <stdio.h>
void fixdLengthfprintf( FILE * _File, float a, int width ) {
if ( !_File ) return;
if ( width < 3 ) return;
int b = a;
do {
width--;
b /= 10;
} while ( b );
width--;
if ( width > 0 ) fprintf( _File, "%.*f\n", width, a );
}
int main( ) {
float numbers[7] = { // prints as:
1.123456, // 1.123456
12.1234567, // 12.12346 (apparently rounded)
123456.0123456, // 123456.0 (heavily rounded)
1234567.0123456, // doesn't get printed
12345678.0123456, // doesn't get printed
123456789.0123456, // doesn't get printed
0.123456789, // 0.123457
};
// I don't allow them to get printed because else they'd look like:
// 1.123456
// 12.12346
// 123456.0
// 1234567
// 12345678.000000
// 123456792.000000
// 0.123457
for ( int i = 0; i < 7; i++ ) fixdLengthfprintf( stdout, numbers[i], 8 );
fflush( stdin );
getchar( );
return 0;
}