对某些标准流类插入和提取浮点数是否保留其值

Does insertion and extraction of a floating point number to some of the standard stream classes preserves its value?

本文关键字:浮点数 提取 是否 保留 插入 标准      更新时间:2023-10-16

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

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不能表示为二进制分数,但它仍然可以被标准流正确格式化。

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

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

(如果您需要同时处理floatdouble,并且不希望对于float上的额外数字,您需要设置精度每次输出一个浮点值)

不,它们不能保证相同。

实际情况是float本身的精度比默认情况下输出的精度高,所以只要你读取的有效数字少于默认输出精度,你输出的结果将(至少通常)四舍五入到你读取的值。

但是,如果您有使用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与我的编译器的float所能表示的最接近的近似值之间的差。

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