如何在 %f 和 %a w/o 之间自动 select 失去精度?
How to automatically select between %f and %a w/o losing precision?
示例代码:
void print_f( float f )
{
...
}
int main( void )
{
print_f( 1.0f ); // prints 1.0
print_f( 29.0f ); // prints 29.0
print_f( 29.13f ); // prints 0x1.d2147ap+4
print_f( 256.0f ); // prints 256.0
print_f( 256.1f ); // prints 0x1.00199ap+8
// and so on
return 0;
}
即如果无法使用 %f
精确打印浮动常量,则使用 %a
。
问题:“使用%f
无法精确打印浮点常量”的条件是什么?
what is the condition for "the floating constant cannot be printed precisely using %f"?
此答案指的是FP常量定义的浮点对象(如double
),并非源码原文
当输出 text/string 不返回原始 double
时,字符串不够精确。
如果OP不想尝试各种精度,那么尝试"%f"
一次。
void print_f(double x) {
char buf[1000];
for (int prec = 0; ; prec++) {
int len = snprintf(buf, sizeof buf, "%.*f", prec, x);
if (len < 0 || (unsigned) len >= sizeof buf) break;
double y = atof(buf);
if (x == y) {
puts(buf);
return;
}
}
printf("%a\n", x);
}
以上使用线性尝试。重写可以尝试 1,2,4,8,16,.... 然后平分到最小值。
备选方案,printf("%.*g\n", DBL_DECIMAL_DIG, x);
接近 OP 的目标,但代码更简单。
示例代码:
void print_f( float f )
{
...
}
int main( void )
{
print_f( 1.0f ); // prints 1.0
print_f( 29.0f ); // prints 29.0
print_f( 29.13f ); // prints 0x1.d2147ap+4
print_f( 256.0f ); // prints 256.0
print_f( 256.1f ); // prints 0x1.00199ap+8
// and so on
return 0;
}
即如果无法使用 %f
精确打印浮动常量,则使用 %a
。
问题:“使用%f
无法精确打印浮点常量”的条件是什么?
what is the condition for "the floating constant cannot be printed precisely using %f"?
此答案指的是FP常量定义的浮点对象(如double
),并非源码原文
当输出 text/string 不返回原始 double
时,字符串不够精确。
如果OP不想尝试各种精度,那么尝试"%f"
一次。
void print_f(double x) {
char buf[1000];
for (int prec = 0; ; prec++) {
int len = snprintf(buf, sizeof buf, "%.*f", prec, x);
if (len < 0 || (unsigned) len >= sizeof buf) break;
double y = atof(buf);
if (x == y) {
puts(buf);
return;
}
}
printf("%a\n", x);
}
以上使用线性尝试。重写可以尝试 1,2,4,8,16,.... 然后平分到最小值。
备选方案,printf("%.*g\n", DBL_DECIMAL_DIG, x);
接近 OP 的目标,但代码更简单。