c++ - std::setprecision设置有效数字的数量。如何使用iomanip设置精度?

标签 c++ iomanip

我总是发现iomanip令人困惑并且反直观。我需要帮助。
快速的互联网搜索发现(https://www.vedantu.com/maths/precision)“因此,我们将精度视为十进制数字中小数点之后的最大有效位数”(重点是我的)。这也符合我的理解。但是我编写了一个测试程序,并且:

stm << std::setprecision(3) << 5.12345678;
std::cout << "5.12345678: " << stm.str() << std::endl;
stm.str("");

stm << std::setprecision(3) << 25.12345678;
std::cout << "25.12345678: " << stm.str() << std::endl;
stm.str("");

stm << std::setprecision(3) << 5.1;
std::cout << "5.1: " << stm.str() << std::endl;
stm.str("");
输出:
5.12345678: 5.12
25.12345678: 25.1
5.1: 5.1
如果精度为3,则输出应为:
5.12345678: 5.123
25.12345678: 25.123
5.1: 5.1
显然,与浮点数有关,C++标准对“精度”的含义有不同的解释。
如果我做:
stm.setf(std::ios::fixed, std::ios::floatfield);
那么前两个值的格式正确,但最后一个为5.100
如何设置精度而不填充?

最佳答案

您可以尝试使用以下解决方法:

decltype(std::setprecision(1)) setp(double number, int p) {
    int e = static_cast<int>(std::abs(number));
    e = e != 0? static_cast<int>(std::log10(e)) + 1 + p : p;
    while(number != 0.0 && static_cast<int>(number*=10) == 0 && e > 1) 
        e--; // for numbers like 0.001: those zeros are not treated as digits by setprecision.
    return std::setprecision(e);
}
然后:
auto v = 5.12345678;
stm << setp(v, 3) << v;

另一个更为冗长和优雅的解决方案是创建一个像这样的结构:
struct __setp {
    double number;
    bool fixed = false;
    int prec;
};

std::ostream& operator<<(std::ostream& os, const __setp& obj)
{
    if(obj.fixed)
        os << std::fixed;
    else os << std::defaultfloat;
    os.precision(obj.prec);
    os << obj.number; // comment this if you do not want to print immediately the number
    return os;
}

__setp setp(double number, int p) {
     __setp setter;
     setter.number = number;
     
    int e = static_cast<int>(std::abs(number));
    e = e != 0? static_cast<int>(std::log10(e)) + 1 + p : p;
    while(number != 0.0 && static_cast<int>(number*=10) == 0)
        e--; // for numbers like 0.001: those zeros are not treated as digits by setprecision.

    if(e <= 0) {
        setter.fixed = true;
        setter.prec = 1;
    } else
        setter.prec = e;
    return setter;
}
像这样使用它:
auto v = 5.12345678;
stm << setp(v, 3);

关于c++ - std::setprecision设置有效数字的数量。如何使用iomanip设置精度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66690841/

相关文章:

c++ - ios_base::xalloc() 和 ostream::iword() (iomanip) 的意外结果

c++ - 当使用模板支持仿函数作为参数时,我应该使用什么限定符?

c++ - 服务器多播 - MFC CSocket - C++ - 如何?

C++ cout 小数对齐

c++ - 为什么需要同时使用 fixed 和 showpoint 操纵器来显示小数点和尾随零,而只有 fixed 才能完成这项工作?

c++ - 读取整数

c++ - 根据 vim 中的语法更改折叠级别

c++ - 简化模板

C++ vector 值不断变化?

c++ - 用 setw 截断