std::to_chars() 最小浮点缓冲区大小

时间:2021-07-21 15:52:52

标签: c++ formatting c++17 number-formatting

给定一个泛型整数类型 IntType,很容易为 base-10 数字确定 std::to_chars 操作所需的缓冲区类型:

std::array<char, std::numeric_limits<IntType>::digits10 + 1 + std::is_signed<IntType>::value> buf;

由于 std::to_chars 不会以 NUL 结尾,并且只添加数字(以及可能的前面 '-',如果有符号),这应该适用于所有内置整数类型。需要 + 1 是因为 digits10 for integral types 返回以 10 为底的对数的下限,而不是上限。

这引出了一个问题:给定一个通用 std::to_chars 的浮点 FloatType 调用的最小缓冲区大小是多少,要在不丢失的情况下进行转换(写入所有十进制数字),使用每个 { {3}} 个值?

1 个答案:

答案 0 :(得分:3)

请注意,所需的最小缓冲区因所需的浮点格式而异。使用 max_digits10max_exponent10 总是足以确定 base-10 输出所需的最少字符数,假设不希望输出比浮点类型包含的精度更高的精度。

这个问题不仅限于to_charsprintf 系列中的 C 标准库函数将具有相同的行为,因此这在 C 中与在 C++ 中的权重相同。

  • std::chars_format::scientific%e (printf specifier)

    template<typename T>
    constexpr int log10ceil(T num) {
        return num < 10? 1: 1 + log10ceil(num / 10);
    }
    
    std::array<char, 4 + 
                     std::numeric_limits<FloatType>::max_digits10 + 
                     std::max(2, log10ceil(std::numeric_limits<FloatType>::max_exponent10))
              > buf;
    

    函数 log10ceil 允许 constexpr 计算最大可能指数中有多少位数字。根据标准,指数中必须至少有 2 位数字,因此要针对最小指数宽度进行测试。写入时使用的精度不得大于 max_digits10 - 1。使用这个精确的精度将提供到字符串表示的无损转换。

    添加的 4 个字符容纳了输出中可能的符号、小数点和 "e+""e-"

  • std::chars_format::fixed%f (printf specifier)

    std::array<char, 2 + 
                     std::numeric_limits<FloatType>::max_exponent10 +
                     std::numeric_limits<FloatType>::max_digits10
              > buf;
    

    同样,使用的精度不能大于 max_digits10 - 1。使用这个精确的精度将提供到字符串表示的无损转换。

    添加 2 个字符以容纳输出中可能的符号和小数点。

  • std::chars_format::general%g (printf specifier)

    对于 general 情况,最小缓冲区始终与 scientific 情况相同。 但是,使用的精度不得大于 max_digits10 以无损转换为字符串表示,而不是如上所述减去一个。

请注意,在所有这些示例中,缓冲区恰好是最大字符串表示的大小。如果需要NUL-终止符或其他内容,则必须相应增加大小。

相关问题