iomanip设置小数点后最多4位

时间:2018-10-01 03:57:16

标签: c++

我想使用iomanip打印显示一些小数点后最多4位数字。

我了解到,在默认模式下,setprecision不仅会计算小数点后的位数,还会计算整数部分的位数。这段代码

#include <iostream>
#include <iomanip>

int main () {
    double numbers[] = {3.141516, 1.01, 200.78901, 0.12345};
    int len = sizeof(numbers) / sizeof(numbers[0]);

    std::cout << std::setprecision(4);
    for (int i = 0; i < len; ++i) {
        std::cout << numbers[i] << '\n';
    }
    return 0;
}

输出:

3.142
1.01
200.8
0.1235

但是我想要的是:(小数点后最多4位,没有尾随零)

3.1415
1.01
200.789
0.1235

iomanip能够做到这一点吗?不用其他技巧(例如round)?

编辑

看来我还不够清楚。我的问题是iomanip特有的

我只想知道iomanip是否能够执行我描述的操作,因为据说iomanip是输入/输出操纵器的标准库。发布的问题是

  

iomanip能够做到这一点吗?

它更像是“是否受支持”而不是“给我任何解决方案”。

我再次搜索它,查找了iomanip个引用,希望找到一种干净紧凑的方法来格式化最多n位的浮点数字,并尽可能少地使用不必要的库。

而且似乎没有实现这一目标的标准方法。

3 个答案:

答案 0 :(得分:0)

获得OP所需输出的一个(丑陋的)选项是代表具有所需最大精度的数字,然后仅删除不想要的零:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>

int main()
{
    std::vector<double> numbers {
        3.141516, 1.01, 200.78901, 0.12345, 9.99999
    };

    for (auto x : numbers)
    {
        // "print" the number
        std::stringstream ss;
        ss << std::fixed << std::setprecision(4) << x;

        // remove the unwanted zeroes
        std::string result{ss.str()};
        while (result.back() == '0')
            result.pop_back();

        // remove the separator if needed   
        if (result.back() == '.')
            result.pop_back();

        std::cout << result  << '\n';
    }

    std::cout << "\nJustified:\n";
    for (auto x : numbers)
    {
        // "print" the number
        std::stringstream ss;
        ss << std::fixed << std::setprecision(4) << std::setw(15) << x;

        // remove the unwanted zeroes
        std::string result{ss.str()};
        auto it = result.rbegin();
        while (*it == '0')
            *it++ = ' ';

        // remove the separator if needed   
        if (*it == '.')
            *it = ' ';

        std::cout << result  << '\n';
    }
}

实时示例:https://ideone.com/8zP17O

答案 1 :(得分:0)

所以:

  • std::fixedfield模式下,std::setprecision设置有效数字的最大数量,而不是小数位;
  • 如果您翻到std::fixed,则表示精确小数位数;
  • C ++不提供%.Nf printf格式字符串的任何类似物! (最多 N 个小数位)

我刚刚组装了一个假的I / O机械手,它可以实现我们都想要的行为。它的性能不是很出色,但是可以完成工作:

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cstdio>

struct sprintf_wrapper
{
    sprintf_wrapper(std::string fmt_str)
        : _fmt_str(std::move(fmt_str))
    {}

    struct proxy
    {
        proxy(const sprintf_wrapper& wrapper, std::ostream& os)
            : _wrapper(wrapper)
            , _os(os)
        {}

        std::ostream& Resolve(const double value) const
        {
            // First find out how many characters we're going to need
            const int len = std::snprintf(nullptr, 0, _wrapper._fmt_str.c_str(), value);
            if (len < 0)
            {
                _os.setstate(std::ios::failbit);
                return _os;
            }

            // Then allocate a buffer
            std::string result;
            result.resize(len);

            // Actually serialise the value according to the format string
            if (std::sprintf(result.data(), _wrapper._fmt_str.c_str(), value) < 0)
            {
                _os.setstate(std::ios::failbit);
                return _os;
            }

            // Stream it out
            _os.write(result.data(), result.size());
            return _os;
        }

        friend std::ostream& operator<<(const proxy& obj, const double val)
        {
            return obj.Resolve(val);
        }

    private:
        const sprintf_wrapper& _wrapper;
        std::ostream& _os;
    };

    friend proxy operator<<(std::ostream& os, const sprintf_wrapper& obj)
    {
        return proxy(obj, os);
    }

private:
    std::string _fmt_str;
};

inline auto sprintf_f(size_t n, const bool showpos = false)
{
    std::stringstream fmt;
    fmt << '%';
    if (showpos) fmt << '+';
    fmt << '.' << n << 'f';

    return sprintf_wrapper(fmt.str());
}

int main()
{
    std::cout << sprintf_f(2) << 4.123456789 << '\n';
    std::cout << sprintf_f(3) << 4.123456789 << '\n';
    std::cout << sprintf_f(4) << 4.123456789 << '\n';
    std::cout << sprintf_f(5) << 4.123456789 << '\n';
    std::cout << sprintf_f(6) << 4.123456789 << '\n';
}

live demo

答案 2 :(得分:-1)

使用std::fixedstd::setprecision的组合。

#include <iomanip>
#include <iostream>

int main() {
    double d = 311.3456;
    std::cout << std::fixed;
    std::cout << std::setprecision(4);
    std::cout << d << std::endl;
}