【问题标题】:Java-style printing of `double` in C++C++中`double`的Java风格打印
【发布时间】:2019-06-19 13:59:35
【问题描述】:

在 C++ 中打印 double 时,是否有任何流操纵器(或标准 C++ 中的任何其他方法)的组合可以让我获得“正确”的位数?

“正确”数字是指here定义的位数:

m 或 a 的小数部分必须打印多少位?必须至少有一个数字来表示小数部分,除此之外,必须有尽可能多的数字,但仅能将参数值与相邻的 double 类型值区分开来。也就是说,假设 x 是由该方法为有限非零参数 d 生成的十进制表示所表示的精确数学值。那么 d 必须是最接近 x 的 double 值;或者如果两个 double 值同样接近 x,则 d 必须是其中之一,并且 d 的有效位的最低有效位必须为 0。

在一个有点简单的例子中,假设我们有三个double 值:DD、D0 和 D1。 DD 是“中间”,D1 尾数大 1,D0 小 1。

当打印到非常大的任意精度时,它们会产生以下值(示例中的数字完全不符合要求):

D0 => 1.299999999701323987
DD => 1.300000000124034353
D1 => 1.300000000524034353

(EPSILON,0指数处尾数的最低有效位的值,约为0.0000000004)

在这种情况下,上面的方法会产生

D0 => 1.2999999997
DD => 1.3
DD => 1.3000000005

【问题讨论】:

  • 您能否编辑您的问题以包含您想要输出特定值的内容?
  • 阅读描述,也许你想使用std::numeric_limits<double>::max_digits10作为精度?
  • 所以基本上你想打印一个没有尾随 0 的双精度数,对吧?
  • 你似乎想要std::to_chars(没有int precision参数的重载),但是编译器对它的支持非常稀缺。
  • @HolyBlackCat 我相信它已在 MSVS 中完全实现并且速度相当惊人。

标签: c++ floating-point


【解决方案1】:

没有尚未在所有地方实现的C++17 library function,您可以尝试精度(使用任何等效于%g)直到精确返回一个回合。如果您不关心次正常数(即使是两位数也可能太多),IEEE 754 双打从 15 开始;永远不会产生无意义的尾随数字。你永远不需要超过 17 岁。

【讨论】:

    【解决方案2】:

    如果我理解正确,你想要std::to_chars

    value 被转换为字符串,就像在默认 ("C") 语言环境中 std::printf 一样。转换说明符是fe(在平局的情况下支持f),根据最短表示的要求进行选择:字符串表示由最少数量的字符组成,使得存在小数点前至少一位(如果存在)并使用相应的std::from_chars 函数解析表示可以准确地恢复值。如果有多个这样的表示,则选择与值差异最小的一个,并根据std::round_to_nearest 使用舍入来解决任何剩余的平局。

    这是一个低级函数,所以打印结果需要一些工作:

    #include <charconv>
    #include <iostream>
    
    int main()
    {
        double val = 0.1234;
    
        char buf[64];
        std::to_chars(buf, buf + sizeof buf, val).ptr = '\0';
    
        std::cout << buf << '\n';
    }
    

    遗憾的是,MSVC 似乎是目前唯一支持precision-less 重载的编译器。

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 2017-04-10
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多