gpt4 book ai didi

c++ - 在不丢失精度但具有最少位数的情况下格式化 double

转载 作者:行者123 更新时间:2023-12-04 15:07:36 35 4
gpt4 key购买 nike

在我们的 C++ 代码库中,我们有一个默认的格式化方法来转换 double将浮点数转换为字符串,特别用于 JSON 序列化和调试日志。对于默认的数字格式,我有以下相互矛盾的要求:

  • 支持人类可读性。首选 10001e30.1251.25e-1 .
  • 保持精度。首选 3.14159265358979313.14 .
  • 避免十进制数的虚假数字。首选 0.10.10000000000000001 .

  • 到目前为止,我发现的最佳折衷是使用等效的 printf("%.15g", value)格式化。它满足要求 1 3 ,但不完全 2 .有大约 4 位的精度损失。
    其他人使用基于 "%.17g" 的默认格式, 满足要求 1 2 ,但不是 3 .号码 0.2 例如格式为 0.20000000000000001 .
    在两者之间,格式 "%.16g"接近满足要求 2 3 ,但并不总是适用于两者。
    作为说明,我希望 0.3 格式为 0.3 , 但是 0.1+0.2 ,由于四舍五入错误而略大,格式为 0.30000000000000004看到差异。
    我编写了以下函数,以我希望的方式格式化浮点数,作为概念证明。然而,从性能的角度来看这是 Not Acceptable ,因为它可以在 double 之间进行多达 34 次转换。和字符串,与 "%.15g" 相比,当前实现的精度增益有限.
    std::string doubleToString(double number)
    {
    char buffer[32];
    long long intVal = static_cast<long long>(number);
    if(intVal == number)
    {
    sprintf(buffer, "%lld", intVal);
    }
    else
    {
    for(int i=1; i<=17; i++)
    {
    sprintf(buffer, "%.*g", i, number);
    double readBack = atof(buffer);
    if(readBack == number)
    break;
    }
    }
    return buffer;
    }
    我刚刚意识到 Python 已经按照我想要的方式格式化数字:
    $ python3
    Python 3.8.6 (default, Oct 8 2020, 14:06:32)
    [Clang 12.0.0 (clang-1200.0.32.2)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 0.3
    0.3
    >>> 0.1+0.2
    0.30000000000000004
    >>>
    有没有办法在不牺牲太多性能的情况下在 C++ 中具有相同的行为?

    最佳答案

    在 Frodyne 发表评论后,我找到了一个非常简单快速的解决方案。
    C++17 std::to_chars默认情况下,函数会格式化浮点数以满足最短往返要求。这意味着所有不同的浮点数在序列化后保持不同,并且最小化要格式化的字符数。
    所以转换可以在标准 C++17 中这样写。

    #include <charconv>
    #include <string>

    std::string doubleToString(double number)
    {
    char buffer[24];
    std::to_chars_result err = std::to_chars(buffer, buffer+sizeof(buffer), value);
    return std::string(buffer, err.ptr);
    }
    微软讲座的好消息是,除了解决最短往返问题外,MSVC中的实现速度非常快!它基于令人难以置信的 Ryu algorithm .
    坏消息是,在撰写本文时 std::to_chars仅适用于 Microsoft 工具链中的浮点数。 Clang libc++ 和 GCC libstdc++ 中的实现目前仅限于整数。

    关于c++ - 在不丢失精度但具有最少位数的情况下格式化 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65810673/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com