C++ 仅使用标准C++;要将任何浮点打印到正好N个空格
我有一个浮点数,我想打印到正好N个空格。例如,N=5。我想打印以下数字:C++ 仅使用标准C++;要将任何浮点打印到正好N个空格,c++,formatting,stream,C++,Formatting,Stream,我有一个浮点数,我想打印到正好N个空格。例如,N=5。我想打印以下数字: 0.1 => 0.1 123.456789 => 123.5 -123.45678 => -123 (or -123.) 0.123456 => 0.123 123456.789 => 123456 (obviously, in this case, we cannot print less than 6 digits, if I can detect this, I can
0.1 => 0.1
123.456789 => 123.5
-123.45678 => -123 (or -123.)
0.123456 => 0.123
123456.789 => 123456 (obviously, in this case, we cannot print less than 6 digits, if I can detect this, I can also print 12** to indicate the field is too wide.
我尝试了许多组合,包括以下组合:
// Leave 3 extra space: One for negative sign, one for zero, one for decimal
std::cout << std::setiosflags(std::ios::fixed)
<< std::setprecision(N - 3)
<< std::setw(N)
<< input;
int main()
{
常数int N=4;
双f=123.456789;
//只需使用默认的浮点表示法来显示N个有效数字。
//没有固定的或科学的符号工作为您的要求。
//如果没有人更改ios::floatfield,则可以将setf()行注释掉。
cout.setf(0,ios::floatfield);
计算精度(N);
cout(最大部分)
{
intpart=ceil(编号);
if(abs(intpart) iostream精度/宽度标志不能很好地满足您的要求-例如,precision
计算有效数字而不是字符位置,4个请求0.123456映射到0.1234而不是您请求的0.123(您是否希望0.00123456为“0.00”?)。无论如何,要使用精度,您需要根据值更改参数。编写自己的函数可能更容易,如下所示
最简单的方法是以更高的精度将值写入stringstream,然后从左向右扫描(记录是否找到“.”),直到到达要截断的点,然后从右向左扫描以删除尾随的0,或者如果之前没有遇到“.”则替换“**”
否则,您可以实现自己的双精度到ASCII转换,可能使用类似linux的
头来提供一个联合,在浮点数
和双精度
类型上提供位字段;否则使用您选择的数学运算。丑陋,但您可能想要:
if(input < pow(10,N+1)) {
ostringstream sout;
sout << input;
cout << setw(N) << sout.str().substr(0,N);
} else cout << (int)input;
#include <cmath>
// determine what precision we need
int precision = N - 1; // leave room for the decimal point
if (input < 0) --precision; // leave room for the minus sign
precision -= (1 + (int)log10(abs(input))); // how many digits before the decimal?
if (precision < 0) precision = 0; // don't go negative with precision
std::cout << std::setiosflags(std::ios::fixed)
<< std::setprecision(precision)
<< std::setw(N)
<< input;
if(输入 sout您似乎想要打印N个字符-包括减号(如果有的话)和小数点。setprecision
只关心小数点后的位数。因此,一点数学可以得到您想要的:
if(input < pow(10,N+1)) {
ostringstream sout;
sout << input;
cout << setw(N) << sout.str().substr(0,N);
} else cout << (int)input;
#include <cmath>
// determine what precision we need
int precision = N - 1; // leave room for the decimal point
if (input < 0) --precision; // leave room for the minus sign
precision -= (1 + (int)log10(abs(input))); // how many digits before the decimal?
if (precision < 0) precision = 0; // don't go negative with precision
std::cout << std::setiosflags(std::ios::fixed)
<< std::setprecision(precision)
<< std::setw(N)
<< input;
- 0-9之间的任何内容都需要一位数字才能打印
- 0-9的log10将给出一个小于1的数字,该数字将截断为int
0
- 10-99之间的任何内容都需要两位数字才能打印
- 10-99的log10给出的数字至少为1,但小于2-截断为int
1
- 所以…log10(输入)加1是它打印的数字数
使用Boost的精神。这方面的业力:
#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;
double d = 12345.6;
// will print: 12345
std::cout << karma::format(
karma::maxwidth(5)[karma::double_], d
) << std::endl;
是的,如果你可能会问,Boost的精神。卡尔玛是用标准的C++特性编写的。< /P>结果,结果如何不好?技术上,代码>代码123456.789 >代码>可以打印在5个空间:<代码> 123e3 < /代码>对于给定的输入,上面提供的输出不符合预期:0.1、123.5、0.1235、1.23 5e+05。(GCC 4.5.2)好吧,我还没有看过它真的-觉得最好是让Dat Chu自己至少有一个裂缝,因为他意识到他不能只使用
精度/setw
/填充
-但是做得很好:-)+1.这类事情似乎很接近,但你可以得到“123”,而不是“123”,并且需要更复杂一点来处理负片。您的解决方案确实非常优雅。我在我的项目中添加了一个CMake选项,如果用户愿意,它将使用Boost.Karma而不是我的解决方案。您是否可以更新您的解决方案以包括Karma::right_align(5),以便输出始终正好是5个字符?如下所述:
precision -= (1 + (int)log10(abs(input))); // how many digits before the decimal?
#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;
double d = 12345.6;
// will print: 12345
std::cout << karma::format(
karma::maxwidth(5)[karma::double_], d
) << std::endl;
if (d < 1e6) {
// d == 12345 will print: 12345
std::cout << karma::format(
karma::maxwidth(5)[karma::double_], d
) << std::endl;
}
else {
// d == 123456 will print: 12***
std::cout << karma::format(
karma::left_align(5, '*')[
karma::maxwidth(2)[karma::double_]
], d
) << std::endl;
}