如何在 C++ 中为浮点值显示多个前导零?
How to display multiple leading zeros for floating point values in C++?
在 C++ 程序中,我想显示一列浮点值,以便符号、数字和小数点都对齐。必要时,多个前导零应填充每个值的整数部分。例如:
A column of floating point values:
+000.0012
-000.0123
+000.1235
-001.2346
+012.3457
-123.4568
我有一个经过精心评论的测试程序可以证明这个问题。但是,当我编辑这个 post 时,我在这里找到了我需要的答案:
- Extra leading zeros when printing float using printf?
根本问题是我在应该使用"%+09.4f"
时使用了格式代码"%+04.4f"
,因为我想要的总字段宽度是9:
- 1 代表牌子
- 3 为整数
- 小数点1
- 小数位数为4
我没有足够的声望点数来评论post,所以在这里谢谢你,@AndiDog。
我仍然不知道如何仅使用流格式化标志来获得多个前导零。但那是另一天的战斗。我现在将坚持混合使用 printf 和流。
要显示正号,请使用 std::showpos。
要显示前导零,请使用 std::setw(n) 和 std::setfill('0')。
要显示零之后的数字,请使用 std::setprecision(m)。
要显示 + 号和第一个数字之间的零,请使用 std::internal。
要将数字保持在固定位置,您可以使用 std::fixed。
#include <iostream> // std::cout, std::fixed
#include <iomanip> // std::setprecision
int main () {
double f =1.234;
double g =-12.234;
std::cout << std::showpos<< std::internal << std::fixed << std::setprecision(4)<<std::setw(9) <<std::setfill('0') << f << '\n';
std::cout <<std::setw(9)<< std::setfill('0') <<g<<"\n"; //repeat these for a new number
return 0;
}
//output:
//+001.2340
//-012.2340
我现在唯一的方法是先显示符号,然后设置填充、宽度和精度,然后显示正值,因为您已经显示了符号。您还需要将格式标志设置为 ios::fixed
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
float x[] = { 000.0012, .0123, .1235, 1.2346, 12.3457, 123.4568 };
cout.setf(ios::fixed);
for (int i = 0; i < 6; i++)
cout << (x[i] > 0 ? '+' : '-') << setfill('0') << setw(8) << setprecision(4) << abs(x[i]) << endl;
return 0;
}
显示器
+000.0012
-000.0123
+000.1235
-001.2346
+012.3457
-123.4568
一些评论提到了 std::setfill('0')
和 std::setw
。虽然这些 是 必需的,但它们不足以完成任务。例如,这段代码:
std::cout << std::setfill('0') << std::setw(7) << std::showpos << 0.012;
将产生:0+0.012
作为其输出。这显然不是我们想要的。
我们需要添加 std::internal
标志来告诉流插入 "internal padding" —— 即,应该在符号和数字的其余部分之间插入填充,所以代码如下:
std::cout << std::setfill('0') << std::setw(7) << std::internal << std::showpos << 0.012;
...产生我们想要的输出:+00.012
.
另请注意,填充字符是 "sticky",因此如果您在对数字类型和非数字类型使用 std::setw
之间交替使用,您可能会 need/want 分别更改它时间。否则,std::cout << setw(12) << name;
之类的结果将产生如下结果:0000000Jerry
,这也很少有人想要。
为了保证小数点后的位数始终相同,我们还需要设置std::fixed
标志,用std::setprecision
指定位数,如:
#include <iostream>
#include <iomanip>
#include <vector>
int main() {
std::vector<double> values { 0.1234, 1.234, 1.5555 };
for (auto d : values)
std::cout << std::internal << std::showpos << std::setw(9)
<< std::setprecision(3) << std::setfill('0') << d << "\n";
}
产生我认为需要的输出:
+0000.123
+0001.234
+0001.556
但在一种情况下您无法通过这种方式获得对齐的结果:如果您的数字太大而无法放入提供的字段中,小数点前的所有位仍将被打印。例如,如果我们在前面的代码要打印的数字列表中添加 1e10
,它将被打印为:+10000000000.000
,这显然不会与其余部分对齐。[=26] =]
解决这个问题的明显方法就是忍受它,如果它出现的频率足以引起关注,请增加字段大小以容纳更大的数字。
另一种可能性是仅在数字低于某个阈值时才使用固定记数法,并切换到(例如)科学记数法来表示更大的数字。
至少根据我的经验,像这样的代码往往主要用于财务数据,在这种情况下,后一种选择通常是不可接受的。
在 C++ 程序中,我想显示一列浮点值,以便符号、数字和小数点都对齐。必要时,多个前导零应填充每个值的整数部分。例如:
A column of floating point values:
+000.0012
-000.0123
+000.1235
-001.2346
+012.3457
-123.4568
我有一个经过精心评论的测试程序可以证明这个问题。但是,当我编辑这个 post 时,我在这里找到了我需要的答案:
- Extra leading zeros when printing float using printf?
根本问题是我在应该使用"%+09.4f"
时使用了格式代码"%+04.4f"
,因为我想要的总字段宽度是9:
- 1 代表牌子
- 3 为整数
- 小数点1
- 小数位数为4
我没有足够的声望点数来评论post,所以在这里谢谢你,@AndiDog。
我仍然不知道如何仅使用流格式化标志来获得多个前导零。但那是另一天的战斗。我现在将坚持混合使用 printf 和流。
要显示正号,请使用 std::showpos。
要显示前导零,请使用 std::setw(n) 和 std::setfill('0')。
要显示零之后的数字,请使用 std::setprecision(m)。
要显示 + 号和第一个数字之间的零,请使用 std::internal。
要将数字保持在固定位置,您可以使用 std::fixed。
#include <iostream> // std::cout, std::fixed
#include <iomanip> // std::setprecision
int main () {
double f =1.234;
double g =-12.234;
std::cout << std::showpos<< std::internal << std::fixed << std::setprecision(4)<<std::setw(9) <<std::setfill('0') << f << '\n';
std::cout <<std::setw(9)<< std::setfill('0') <<g<<"\n"; //repeat these for a new number
return 0;
}
//output:
//+001.2340
//-012.2340
我现在唯一的方法是先显示符号,然后设置填充、宽度和精度,然后显示正值,因为您已经显示了符号。您还需要将格式标志设置为 ios::fixed
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
float x[] = { 000.0012, .0123, .1235, 1.2346, 12.3457, 123.4568 };
cout.setf(ios::fixed);
for (int i = 0; i < 6; i++)
cout << (x[i] > 0 ? '+' : '-') << setfill('0') << setw(8) << setprecision(4) << abs(x[i]) << endl;
return 0;
}
显示器
+000.0012
-000.0123
+000.1235
-001.2346
+012.3457
-123.4568
一些评论提到了 std::setfill('0')
和 std::setw
。虽然这些 是 必需的,但它们不足以完成任务。例如,这段代码:
std::cout << std::setfill('0') << std::setw(7) << std::showpos << 0.012;
将产生:0+0.012
作为其输出。这显然不是我们想要的。
我们需要添加 std::internal
标志来告诉流插入 "internal padding" —— 即,应该在符号和数字的其余部分之间插入填充,所以代码如下:
std::cout << std::setfill('0') << std::setw(7) << std::internal << std::showpos << 0.012;
...产生我们想要的输出:+00.012
.
另请注意,填充字符是 "sticky",因此如果您在对数字类型和非数字类型使用 std::setw
之间交替使用,您可能会 need/want 分别更改它时间。否则,std::cout << setw(12) << name;
之类的结果将产生如下结果:0000000Jerry
,这也很少有人想要。
为了保证小数点后的位数始终相同,我们还需要设置std::fixed
标志,用std::setprecision
指定位数,如:
#include <iostream>
#include <iomanip>
#include <vector>
int main() {
std::vector<double> values { 0.1234, 1.234, 1.5555 };
for (auto d : values)
std::cout << std::internal << std::showpos << std::setw(9)
<< std::setprecision(3) << std::setfill('0') << d << "\n";
}
产生我认为需要的输出:
+0000.123
+0001.234
+0001.556
但在一种情况下您无法通过这种方式获得对齐的结果:如果您的数字太大而无法放入提供的字段中,小数点前的所有位仍将被打印。例如,如果我们在前面的代码要打印的数字列表中添加 1e10
,它将被打印为:+10000000000.000
,这显然不会与其余部分对齐。[=26] =]
解决这个问题的明显方法就是忍受它,如果它出现的频率足以引起关注,请增加字段大小以容纳更大的数字。
另一种可能性是仅在数字低于某个阈值时才使用固定记数法,并切换到(例如)科学记数法来表示更大的数字。
至少根据我的经验,像这样的代码往往主要用于财务数据,在这种情况下,后一种选择通常是不可接受的。