如何在 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:

我没有足够的声望点数来评论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] =]

解决这个问题的明显方法就是忍受它,如果它出现的频率足以引起关注,请增加字段大小以容纳更大的数字。

另一种可能性是仅在数字低于某个阈值时才使用固定记数法,并切换到(例如)科学记数法来表示更大的数字。

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