精确且无容忍地将float转换为字符串

时间:2018-05-31 14:15:39

标签: c++ floating-point precision

如何在没有容差的情况下将float转换为具有指定精度的字符串? 例如,使用精度6得到以下结果。

40.432 -> 40.432000.

在一个字符串中,我能得到的唯一值是40.431999。

2 个答案:

答案 0 :(得分:0)

  

如何将float转换为具有指定精度的字符串

您可以使用字符串流:

std::ostringstream strs;
strs << std::fixed << std::setprecision(6)  << the_value;
std::string str = strs.str();
  

在一个字符串中,我能得到的唯一值是40.431999。

您的问题可能是系统使用的浮点格式中没有40.432的确切表示。由于您永远不会有浮点值40.432,因此您永远不能将此值转换为字符串。

恰好相反,40.432的最接近的可表示值接近40.431999而不是40.432。

你需要:

  1. 接受40.432 ~~ 40.431999
  2. 或者使用足够精确的浮点格式,使40.432的表示形式比40.431999更接近40.432,并且对于具有特定预期值的所有其他数字也足够精确。 IEEE 754双精度浮点碰巧具有比40.431999更接近40.432的可表示值。
  3. 或停止使用浮点。如果你使用定点或任意精度数据类型,你不会遇到这样的问题。

答案 1 :(得分:0)

问题是您使用的float数据类型的精度只有at most 7.22 total digits,有时只有6位数,而您尝试显示的总数为8位(2小数点前和后6点)。如评论中所述,最接近的二进制浮点数为40.432是40.43199920654296875,第二个最接近的是40.432003021240234375。

通过转换为较大的double类型,您可以获得更多数字。完成后,您可以舍入到最接近的6位数字。请注意,如果float是通过计算生成的,则舍入实际上可能会创建较少的准确结果。

如果你总是知道你的数字在10到100之间,那么这个简单的代码就可以了。否则,您将需要一个更复杂的过程来确定适当的舍入量。

float f = 40.432;
double d = f;
double r = std::round(d * 10000.0) / 10000.0; // 2 digits before the decimal, 4 after
std::cout << std::fixed << std::setprecision(6) << r;

请注意,由于四舍五入,最后2位数始终为零。

查看实际操作:http://coliru.stacked-crooked.com/a/f085e56c03ebeb73