【问题标题】:Convert float to std::string without losing precision. Also I don't want to use sprintf将 float 转换为 std::string 而不会丢失精度。我也不想使用 sprintf
【发布时间】:2019-02-06 16:27:58
【问题描述】:

我想在 std::string 中转换浮点值,即 3.14159267 我不想使用 sprintf

#include <iostream>   // std::cout
#include <string>     // std::string, std::to_string

int main ()
{
  std::string pi = "pi is " + std::to_string(3.14159267);
  std::cout<<pi<<std::endl;
  return 0;
}

我得到的结果是 3.141593

【问题讨论】:

  • 好吧,你不能。在浮点数和十进制表示之间转换时,您总是会丢失一些精度。
  • @freakish 不,如果你做对了,你就不会。
  • stringstream 不会处理这个吗?
  • Dup targ 无效,dup 是关于打印完整精度 double。这个问题清楚地打印出一个字符串,所以精度丢失是因为std::to_string,而不是std::cout。重新开放。
  • 你可能不明白数字和它的表示之间的区别。你应该问自己“任意两个数字之间有多少个数字?”。

标签: c++


【解决方案1】:

如果你只想打印出来:

std::cout<< std::setprecision(9) << 3.14159267 << std::endl;

如果要设置字符串的精度:

  double pi = 3.14159265359;
  std::stringstream stream;
  stream << std::setprecision(9) << pi;
  std::string pi_string = stream.str();
  std::cout<< "Pi:" << pi_string << std::endl;

【讨论】:

  • 我不知道float值的长度是多少,所以无法提前设置精度。
  • 你不需要知道长度。 Float 的精度始终为 6。因此您可以将 std::setprecisio 排除在外。顺便说一句:您的 PI (3.14159267) 需要双精度
  • 您的第一个示例可能无法按预期工作,因为某些流操纵器具有粘性,并且有人可能在此行之前完成了std::cout &lt;&lt; std::fixed;。 IMO,使用std::ostream 进行数字格式化似乎更加微妙而且过于冗长。试试std::cout &lt;&lt; std::fixed &lt;&lt; std::setprecision(9) &lt;&lt; 0.000000000314159267 &lt;&lt; '\n';
【解决方案2】:

理论上,这应该适用于符合 C++17 的编译器(并且应该是快速且独立于语言环境的):

#include <charconv>

const double pi = 3.14159267;
const int prec = 6;
char buffer[100];

auto [ptr, ec] = std::to_chars(buffer, std::end(buffer),
    pi, std::chars_format::fixed, prec);

不幸的是,它没有,即使是 gccclang 的主干版本。似乎P0067R5 实现起来并不那么明显,另请参阅cppreference compiler support(搜索“P0067R5”)或this reddit thread

【讨论】:

    【解决方案3】:

    我建议您使用格式说明符 "%.16g" 调用 snprintf - 以十进制形式打印 double,精度为 16 位有效数字。有关详细信息,请参阅Number of Digits Required For Round-Trip Conversions。例如:

    inline std::string as_string(double value) {
        char buf[32];
        return std::string(buf, std::snprintf(buf, sizeof buf, "%.16g", value));
    }
    

    *printf 函数是基本的转换例程,其他一切都使用这些。

    std::to_string 在 GNU C++ 标准库中:

    inline string to_string(double __val)  {
      const int __n =  __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
      return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n, "%f", __val);
    }
    

    std::ostream 还在后台调用 *snprintf 来格式化数字。


    还要注意3.14159267doublefloat 常量需要 f 后缀,例如3.14159267f.

    【讨论】:

      猜你喜欢
      • 2010-10-29
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      相关资源
      最近更新 更多