std::to_chars() 最小浮点缓冲区大小
std::to_chars() minimal floating point buffer size
给定通用整数类型 IntType
,很容易确定 std::to_chars
以 10 为基数的操作所需的缓冲区类型:
std::array<char, std::numeric_limits<IntType>::digits10 + 1 + std::is_signed<IntType>::value> buf;
因为 std::to_chars
不以 NUL 终止,并且只添加数字(如果有符号,可能前面还有 '-'
),这应该适用于所有内置整数类型。 + 1
是必需的,因为 digits10 for integral types returns 以 10 为底的对数的下限,而不是上限。
这引出了一个问题:给定要无损转换(写入所有十进制数字)的通用 FloatType
,浮点 std::to_chars
调用的最小缓冲区大小是多少,使用每个std::chars_format
值?
请注意,所需的最小缓冲区因所需的浮点格式而异。使用 max_digits10
和 max_exponent10
总是足以确定 base-10 输出所需的最少字符数,假设不希望输出比浮点类型包含的精度更高的精度。
这个问题也不仅仅限于to_chars
。 printf
系列中的 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 终止符或其他内容,则必须相应增加大小。
给定通用整数类型 IntType
,很容易确定 std::to_chars
以 10 为基数的操作所需的缓冲区类型:
std::array<char, std::numeric_limits<IntType>::digits10 + 1 + std::is_signed<IntType>::value> buf;
因为 std::to_chars
不以 NUL 终止,并且只添加数字(如果有符号,可能前面还有 '-'
),这应该适用于所有内置整数类型。 + 1
是必需的,因为 digits10 for integral types returns 以 10 为底的对数的下限,而不是上限。
这引出了一个问题:给定要无损转换(写入所有十进制数字)的通用 FloatType
,浮点 std::to_chars
调用的最小缓冲区大小是多少,使用每个std::chars_format
值?
请注意,所需的最小缓冲区因所需的浮点格式而异。使用 max_digits10
和 max_exponent10
总是足以确定 base-10 输出所需的最少字符数,假设不希望输出比浮点类型包含的精度更高的精度。
这个问题也不仅仅限于to_chars
。 printf
系列中的 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 终止符或其他内容,则必须相应增加大小。