【问题标题】:format floating point number to a char array of limited size with optional decimal point将浮点数格式化为带有可选小数点的有限大小的 char 数组
【发布时间】:2021-04-26 18:32:18
【问题描述】:

我需要将浮点数打印为固定数量的字符。这用于严格基于文本的数据协议(是的,我知道)。十进制包含在字符数中。忽略空终止符。没有最小填充要求。十进制精度可以是 0 到(缓冲区大小 - 2),而最大实数可以是 0 到缓冲区大小。最小和最大值钳制以防止真正超出范围的数字在此问题的外部处理。

假设缓冲区大小为 6 且强制最小值和最大值为(0.0001 和 999999)的示例:

Original Buffer (6 chars) Notes
12445.11897784 12445 Only the 5 digts are kept as there is no room for decimal + value
8846.51548 8846.5
4.54631888315 4.5463
7651 7651
0.87457 .87457 0.8746 would also be acceptable

起初我认为 sprintf 和 %.6G 似乎可以工作,直到我意识到它没有将小数点作为字符考虑在内。我的理解不完整吗?

是否有任何 C++17 或更低版本的实用程序可以用来完成上述操作。我也愿意考虑将或已经成为高于 c++17 版本标准的一部分的库。

【问题讨论】:

  • Is my understanding incomplete?你的理解是什么?
  • 考虑snprintf
  • Is there any utilities in C++17您是在寻找实用程序还是想解决您的问题?
  • {fmt} 现在越来越流行

标签: c++ formatting c++17


【解决方案1】:

这是一个 C++ 17 版本:

#include <iostream>
#include <charconv>

std::string to6(float f) {
    std::string s;
    s.resize(10);
    auto ec = std::to_chars(s.data(), s.data() + s.size(), f, std::chars_format::fixed);
    s.resize(6);
    if (s.back() == '.')
        s.resize(5);
    return s;
}

int main()
{
    std::cout << to6(12445.11897784) << std::endl;
    std::cout << to6(8846.51548) << std::endl;
    std::cout << to6(4.54631888315) << std::endl;
    std::cout << to6(7651) << std::endl;
    std::cout << to6(0.87457) << std::endl;
    return 0;
}

注意:我没有检查错误,因为

最小和最大值钳制以防止真正超出范围的数字在此问题的外部处理。

【讨论】:

    【解决方案2】:

    看起来很简单:

    1. 如果数字大于 10000
      1. 正常打印,不带数字%.0f
    2. 如果数字大于 1000
      1. 在逗号%.1f后面加一位数字
    3. 如果数字大于 100
      1. 在逗号%.2f之后打印两位数
    4. 如果数字大于 10 2. 逗号%.3f后3位打印
    5. 如果... 1
      1. ...%.4f
    6. 其他
      1. %.5f
      2. 删除前导零

    注意四舍五入!前任。数字 9.999999 低于 10,但它会打印为 10.000。正因为如此:

    1. 首先将所需精度最高的数字 - %.5f - 打印到字符串中。
    2. 然后计算结果字符串中逗号前的数字
    3. 然后对逗号前的 count 位数进行上述比较“如果一个数字大于 100”,而不是实际数字。
    4. 将字符串修剪为逗号后所需的位数。

    即。在打印之后而不是在打印之前处理字符串中正确舍入的数字,这样可以防止在转换为字符串时更改数字的任何舍入。

    【讨论】:

      猜你喜欢
      • 2011-09-15
      • 2011-07-08
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2019-01-06
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多