如何在c++中显示浮点值的多个前导零

How to display multiple leading zeros for floating point values in C++?

本文关键字:c++ 显示      更新时间:2023-10-16

在一个c++程序中,我想显示一列浮点值,以便符号、数字和小数点都对齐。必要时,应在每个值的整数部分填充多个前导零。例如:

A column of floating point values:
  +000.0012
  -000.0123
  +000.1235
  -001.2346
  +012.3457
  -123.4568

我有一个精心注释的测试程序来演示这个问题。但是,当我在编辑这篇文章时,我在这里找到了我需要的答案:
-使用printf?打印浮动时额外的前导零?

基本问题是,当我应该使用"%+09.4f"时,我使用了"%+04.4f"的格式代码,因为我想要的总字段宽度是9:

  • 1表示
  • 标志
  • 3为整数
  • 1为小数点
  • 4表示小数

我没有足够的声望点来评论那篇文章,所以在这里谢谢你,@AndiDog。

我仍然不知道如何使用流格式标志获得多个前导零。但这是另一天的战斗。现在我将坚持使用printf和stream的混合。

有几个评论提到了std::setfill('0')std::setw。虽然这些是必要的,但它们对任务来说是不够的。例如,下面的代码:

std::cout << std::setfill('0') << std::setw(7) << std::showpos << 0.012;

将产生:0+0.012作为其输出。这显然不是我们想要的。

我们需要添加std::internal标志来告诉流插入"内部填充"——也就是说,填充应该插入到符号和数字的其余部分之间,所以像这样的代码:

std::cout << std::setfill('0') << std::setw(7) << std::internal << std::showpos << 0.012;

+00.012 .

还要注意,填充字符是"粘性的",所以如果你交替使用std::setw与数字和非数字类型,你可能需要/想要每次改变它。否则,类似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,这显然不会与其他数字对齐。

处理这个问题的最明显的方法就是忍受它,如果它经常出现,那么就增加字段的大小以容纳更大的数字。

另一种可能性是只在数字低于某个阈值时使用固定记数法,而对于较大的数字则切换为(例如)科学记数法。

至少在我的经验中,像这样的代码往往主要用于财务数据,在这种情况下,后一种选择通常是不可接受的。

要显示正号,可以使用std::showpos。

要显示前导零,使用std::setw(n)和std::setfill('0')。

显示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