【问题标题】:Maximum allowed value of the precision format specifier in the {fmt} library{fmt} 库中精度格式说明符的最大允许值
【发布时间】:2022-01-04 10:15:00
【问题描述】:

考虑以下 sn-p1(可测试 here):

#include <fmt/core.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

// Let's see how many digits we can print
void test(auto value, char const* fmt_str, auto std_manip, int precision)
{
    std::ostringstream oss;
    oss << std_manip << std::setprecision(precision) << value;
    auto const std_out { oss.str() };
    auto const fmt_out { fmt::format(fmt_str, value, precision) };    
    std::cout << std_out.size() << '\n' << std_out << '\n'
              << fmt_out.size() << '\n' << fmt_out << '\n';
}

int main()
{
    auto const precision{ 1074 };
    auto const denorm_min{ -0x0.0000000000001p-1022 };

    // This is fine
    test(denorm_min, "{:.{}g}", std::defaultfloat, precision);
    
    // Here {fmt} stops at 770 chars
    test(denorm_min, "{:.{}f}", std::fixed, precision);  
}

根据{fmt}库的documentation

precision 是一个十进制数,表示对于格式为'f''F' 的浮点值,或小数点前后应显示多少位数对于格式为 'g''G' 的浮点值。

这个值有限制吗?

在我发布的角落案例中,std::setprecision 似乎能够输出所有 请求的数字,而{fmt} 似乎停止在 770(公平地说,在大多数情况下,这是一个“合理”足够大的值)。有没有我们可以设置的参数来修改这个限制?

编辑

我向图书馆管理员报告了issue,现在似乎是fixed


(1) 如果您想知道这些特定值的来源,我正在玩这个问答:
What is the maximum length in chars needed to represent any double value?

【问题讨论】:

    标签: c++ fmt


    【解决方案1】:

    精度可以是小于 max int 的任何值。

    您观察到的是一个现在已修复的错误,即处理固定浮点格式的超大精度:https://github.com/fmtlib/fmt/issues/2616(感谢报告)。

    767 不是精度限制,而是 IEEE754 double 可以具有的最大有效位数(其余为 0):https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/

    【讨论】:

    • 速度很快,非常感谢。我最终弄清楚了该数字的含义,但再次感谢您的参考。如果可以,我是否正确假设没有格式说明符会自动输出 all 十进制表示的有效数字(包括前导零),但 没有 尾随零(使用足够大的精度值输出)?
    • 不适用于固定精度,但默认格式将为您提供足够的有效数字来进行往返(其余的大多没有意义)。
    【解决方案2】:

    离你不远了,format-inl.h 文件 (see here) 中有一个硬编码限制为 767:

    // Limit precision to the maximum possible number of significant digits in
    // an IEEE754 double because we don't need to generate zeros.
    const int max_double_digits = 767;
    if (precision > max_double_digits) precision = max_double_digits;
    

    【讨论】:

    • 我明白了,谢谢。在我的示例中,额外的 3 个字符是前导 "-0."。不过,不确定他们从哪里获得最大有效数字的“神奇”数字。
    • 如果您认为该值应该更高(或可修改),则可以在其 GitHub 上的问题跟踪器中添加错误或提交拉取请求,维护人员应该能够告诉您在哪里号码来自
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 2014-07-25
    • 2015-12-24
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    相关资源
    最近更新 更多