【问题标题】:Truncate double when passing to stingstream传递给 stingstream 时截断双倍
【发布时间】:2015-07-17 08:50:40
【问题描述】:

我遇到了双精度问题。

std::stringstream ss;
ss << std::setprecision(std::numeric_limits<double>::digits10) << std::numeric_limits<double>::max();

这会将1.79769313486232e+308 打印到刺痛处,而实际上双倍最大值是1.79769313486231XXXXe+308。所以再次读取这个字符串流会导致无穷大。

如何截断数字而不是四舍五入?

【问题讨论】:

  • 浮点值总是很难存储为人类可读的字符串。如果这不是强制性的,您应该考虑将浮点(或双精度)值存储为二进制 blob。或者您可以将它们转换为 uint64_t(请参阅 reinterpret_cast(double*))以避免任何精度损失,但存储的表示形式将不适合人类阅读...
  • 它不能重读Double max,但应该是它附近的东西。并且字符串必须是人类可读的,因为它被放入可以手动编辑的配置文件中
  • 为什么不std::trunc
  • 它向自然数截断。所以我必须添加逻辑将我的号码转换为179769313486231.XXXX,截断它并将其转换回1.79769313486231e+308。但看起来我必须这样做...... :(

标签: c++ double std stringstream


【解决方案1】:

四舍五入来自许多系统使用的 IEEE-754 浮动类型标准。原因是您只能表示有限精度的数字。其中一种浮点表示是由 IEEE-754 标准化的。

如果你想在某些特定数字之后截断数字,那么你可以使用std::trunc函数,你可以在mathcmath头文件中找到。

如果您只想在输出流上截断它,那么您可以通过 #include&lt;iomanip&gt; 头文件使用 setprecision 指令。

为了调整舍入操作,您可以设置一些编译器标志。 gcc 的一个示例是快速数学编译器标志。 (更多信息请看这里gcc floating point compiler flags

编辑 根据我在这里的评论,您将找到有关将浮动类型转换为非浮动类型然后转换为二进制补码的更多信息。 因此,有关更多信息,请参见此处: truncating floats convert to two's complement and further information for rounding-error evaluation

您还可以尝试将浮点数加载到SSE,AVX, ... (depends on your system)

【讨论】:

  • -1(如果我有足够的声誉):我使用setprecision,它会四舍五入并且不会截断。当然我可以在转换为字符串之前使用trunc,但我想知道是否有可以设置为自动执行此操作的字符串流属性。
  • @kuga 如果您想知道“是否存在可以设置为自动执行此操作的 stringstream 的属性”,请在您的问题中说出来。 mbed_dev 无法读懂你的想法。
  • @kuga 正如答案中所说,那么您必须使用使用编译器标志的调整方法。当然stringstream 有像stringstreamvar.precision(x) 这样的精度设置方法,但它仍然会四舍五入。因此,要么查看编译器标志,要么将浮点类型转换为非浮点类型,然后以二进制补码形式分析您的精度。
  • @Andy:我认为标题中是这样的。但没关系。
  • @mbed_dev:感谢您的解释。我无法更改编译器标志,因为它可能会影响该文件中的其他转换,老实说,我不喜欢这些东西。
猜你喜欢
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多