动态格式化固定点数

时间:2015-09-08 12:27:35

标签: c++ floating-point string-formatting

我需要格式化浮点数(表示为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. 最后,我还需要添加千位分隔符

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

然而,由于这不是直截了当,在某些情况下会失败。

但我的问题是:

有没有简单的方法,我可以在没有这些混乱的情况下使用它?

2 个答案:

答案 0 :(得分:1)

您可以使用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";
    }
}

答案 1 :(得分:1)

这非常简单,似乎可以根据您的规范工作。

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());
}