定点数的动态格式化

Dynamic Formatting of a fixed point number

我需要格式化一个浮点数(表示为 std::string),其中输出最多有 14 位数字,包括整数部分和小数部分。

虽然限制为14位,但整数部分最多可以有14位(然后没有小数部分),小数部分最多可以有7位(然后整数部分有7位)

**Examples**
123
123.456
12345678901234
1234567.89
1234.5678901
1234567890123.4
1234567890123.456 // Invalid; Should be transformed to 1234567890123.4
123456789012345.6 // Invalid; Should be transformed to 12345678901234

思路是保留length =< 14,小数位数最大为7。最后,我还需要加上千位分隔符.

当前方法 目前,我尝试使用小数点拆分字符串并提取数字的两部分。 (如果没有".",则另行处理)。然后检查整数部分和小数部分的大小。

但是,由于这不是直截了当的,因此在某些情况下会失败。

但我的问题是:

有没有什么简单的方法,我可以使用而没有这些混乱?

您可以使用 Boost.Format。这是一个通过您的测试用例的示例:

#include <iostream>
#include <iomanip>

#include <boost/format.hpp>

int main()
{
    std::vector<std::string> examples = {
        "123",
        "123.456",
        "12345678901234",
        "1234567.89",
        "1234.5678901",
        "1234567890123.4",
        "1234567890123.456",
        "123456789012345.6" 
    };
    std::string format = "%1$.15s";
    for (auto example : examples)
    {
        std::cout << boost::format(format) % example << "\n";
    }
}

这非常简单,似乎符合您的规范。

std::string format(string str)
{
    // Are there any decimals?
    int dot = str.find(".");
    if (dot < 0)
    {
        return str.substr(0, 14);
    }

    std::string integral = str.substr(0, dot);
    size_t intlength = integral.length();

    // Too long to care about decimals?
    if (intlength >= 14)
    {
        return integral.substr(0, 14);
    }

    // Keep at most seven decimals
    std::string decimals = str.substr(dot + 1, 7);
    size_t declength = decimals.length();

    // Is concatenation short enough?
    if (intlength + declength <= 14)
    {
        return integral + "." + decimals;
    }

    return integral + "." + decimals.substr(0, 14 - integral.length());
}