我想使用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
位的浮点数字,并尽可能少地使用不必要的库。
而且似乎没有实现这一目标的标准方法。
答案 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';
}
}
答案 1 :(得分:0)
所以:
std::fixedfield
模式下,std::setprecision
设置有效数字的最大数量,而不是小数位; std::fixed
,则表示精确小数位数; %.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';
}
答案 2 :(得分:-1)
使用std::fixed
和std::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;
}