3

当我调试时,有时我想打印一个函数返回的浮点数并将其用作另一个函数的输入值。我想知道指导浮点数格式的默认参数是什么。

以下代码中的 f1 和 f2 是否始终相同?

#include <sstream>
#include <cassert>
int main(int argc, const char *argv[])
{
  std::stringstream ss;

  float f1 = .1f;
  ss << f1;

  float f2;
  ss >> f2;

  assert(f1 == f2);
  return 0;
}

我可以将一堆浮点数写入 std::cout 或 std::ofsteam 并将它们读回以获得完全相同的数字还是应该明确设置小数点后的数字数量(就像这里建议的那样?

困扰我的是,虽然 .1 不能表示为二进制分数,但它仍然可以由标准流正确格式化。

4

3 回答 3

6

不必要。默认情况下,ostream输出 6 位精度。为了能够“往返”一个浮点数,您需要一个精度std::numeric_limits<float>::max_digits10(最常见的表示为 9)。如果流被用于持久性,而你只是持久化浮点数,只需在写入任何内容之前设置精度,例如:

ss.precision( std::numeric_limits<float>::max_digits10 );

(如果您需要同时处理floatdouble,并且不希望在 上出现多余的数字float,则每次输出浮点值时都需要设置精度。)

于 2013-04-11T15:56:23.843 回答
1

不,不能保证它们是相同的。

发生的情况是浮点数本身的精度比默认情况下打印出来的要高,所以只要你读入的有效数字少于默认输出精度,你打印出来的内容(至少通常)会被四舍五入回到你读入的值。

但是,如果您的数据使用了您的float.

#include <sstream>
#include <iomanip>
#include <iostream>

int main() { 
    std::istringstream buffer("0.1");
    float value;
    buffer >> value;
    std::cout << value << "\n"; 
    std::cout << std::setprecision(10) << value;
}

结果:

0.1
0.1000000015

在这种情况下,尾随15是(大约)0.1 与我的编译器的浮点数可以表示的最接近的近似值之间的差异。

于 2013-04-11T16:01:40.467 回答
-1

更重要的是,assert(f1 == f2); 当 f1 和 f2 都是浮点数时很少是正确的。你想要类似 assert(abs(f1 - f2) < tolerance); 有几种通常用于选择公差的技术。您应该使用哪一个取决于您的程序正在解决的问题。

于 2013-04-11T16:00:47.883 回答