如何避免 `std::to_string()` 将一个非常小的双精度数变为 0?

问题描述 投票:0回答:3

我需要将非常小的双数存储为字符串格式,然后反转它们。然而,当我尝试在像

std::to_string()
这样的小数字上运行
4.7816457028269855e-143
时,它只会使其变为 0。

我提到了转换浮点值时设置 std::to_string 的精度及其链接的副本。但是将精度设置为很大的数字可以在所有平台上解决这个问题吗?

如何解决这个问题?
使用

to_string()
的任何替代品都可以。

c++ floating-point double c++14 tostring
3个回答
2
投票

不,问题不在于精度,而在于格式。您想以科学格式(带指数)打印,但

std::to_string()
默认使用固定格式,我不知道有什么方法可以改变它。

但是,如果合适,流会使用科学,或者您可以使用

std::scientific
:

强制使用它
std::ostringstream oss;
oss << 4.7816457028269855e-143;
std::string numberAsString = oss.str(); // stores "4.78165e-143"  

当然除此之外您还可以增加精度

如果出于某种原因您不想使用科学格式,您可以使用精度足够高的固定格式。在这种情况下,“足够高”意味着超过 142,因为将有 142 个前导零:

oss << std::fixed << std::setprecision(142 + x);

但我认为科学格式更适合。


2
投票

正如已经提到的,用

std::to_string
不可能实现这一点,但是以足够大的精度将数字输出到
std::ostringstream
将解决您的问题。

可以使用 C++ 标准库工具以跨平台方式计算所需的精度,特别是

std::numeric_limits<T>::max_digits10
常量:https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10

例如:

std::string to_string_exact(double x) {
  std::ostringstream os;
  os << std::setprecision(std::numeric_limits<double>::max_digits10) << x;
  return os.str();
}

另请参阅https://possiblewrong.wordpress.com/2015/06/21/floating-point-round-trips/了解一些注意事项。


0
投票

这是

std::to_string
的一个已知问题,已在 C++26 中修复。

© www.soinside.com 2019 - 2024. All rights reserved.