设置精度和剪辑尾随零但从不打印指数

我需要:

  1. 设置精度,使浮点数舍入到百分位数(0.111打印为0.11)
  2. 剪辑尾随零(1.0打印为1)
  3. 永远不要打印指数(1000.1打印为1000.1)

printf( "%.2f\n", input ); // handles 1 and 3 but not 2
printf( "%.2g\n", input ); // handles 1 and 2 but not 3
cout << setprecision( 2 ) << input << endl; // handles 1 and 2 but not 3

是否有printfcout选项可以让我处理所有这些?

C11标准表示%f%F (7.21.6.1:8):

表示浮点数的双参数在样式[ – ] ddd.ddd中转换为十进制表示法,其中小数点字符后面的位数等于精度规范。 如果精度丢失,则取6; 如果精度为零且未指定#flag,则不显示小数点字符。 如果出现小数点字符,则在其前面至少出现一个数字。 该值四舍五入到适当的位数。

这是一个C片段,可以在malloc ed bloc中生成您想要的内容,然后您需要释放它。 如果您使用C99编写,也可以考虑使用可变长度数组。

下面的代码没有引入任何额外的转换近似值(如果你的printf打印正确的舍入转换为十进制,下面的代码也是如此),并适用于所有浮点值。

 #include  #include  … int len = snprintf(0, 0, "%.2f", input); if (len < 0) fail(); char *t = malloc((size_t)len + 1); if (!t) fail(); if (sprintf(t, "%.2f", input) < 0) fail(); len--; if (t[len] == '0') { len--; if (t[len] == '0') { len--; if (t[len] == '.') len--; } t[len + 1] = '\0'; } 

我不知道任何格式说明符会做你想要的。

在将值传递给单独的格式说明符之前预先消化值可能有效。 例如:

  • 将原始浮点数乘以100并舍入为最接近的整数
  • 分配给nScaled(int)。
  • 将mod(nScaled,100)分配给另一个整数nFractional。
  • 将nScaled / 100分配给另一个整数nWhole。

 if( nFractional > 0 ) printf("%d.%d", nWhole, nFractional ); else printf("%d", nWhole ); 

你可能已经知道了。

我认为另一个选择是使用asprintf()函数:它自动动态分配一个适当长度的字符串。 存储字符串后,可以删除尾随零/点:

 ... float num; ... char *digits; int i=asprintf(&digits, "%.2f", num)-1; for(; digits[i] !='.'; i--) if (digits[i] == '0') digits[i] = NULL; else break; if (digits[i] == '.') digits[i] = NULL; printf("%s\n", digits); free(digits); ... 

遗憾的是,没有办法强制流使用printf%f行为。 因此,处理此问题的唯一方法是根据需要手动修剪小数位。 我添加了一个处理此问题的C ++代码示例:

 string fullfloat(static_cast(log10(numeric_limits::max())) + 5U, '\0'); // Adding 1 for the 10s place, 1 for the '.' 2 for the decimal places, and 1 for the null const size_t length = size(fullfloat) - sprintf(data(fullfloat), "%.2f", input ); *(--mismatch(rbegin(fullfloat) + length, next(rbegin(fullfloat), 3U + length), "00.").first) = '\0'; 

fullfloat现在将包含正确的字符串,但因为它的大小将延伸超过应用的'\0'字符,将其打印属性的唯一方法是使用data()

 cout << data(fullfloat);