HOWTO · C++

C++ で setprecision を使用する方法

この記事では、C++ のストリームマニピュレータである `setprecision()` の使い方を紹介します。

このページの内容

C++ では、std::setprecision(n) を使うと、ストリームに続けて出力する浮動小数点値の精度を設定できます。既定の浮動小数点形式では、n は有効桁数を表し、小数点以下の桁数を表すわけではありません。小数点以下の桁数を一定にしたい場合は、std::fixed を追加します。

setprecision は、<iomanip> で宣言されているストリームマニピュレータです。以下の例では std::cout を使いますが、同じ書式状態の規則はほかの出力ストリームにも当てはまります。

setprecision が精度を制御する仕組み

std::fixed も std::scientific も指定しない場合、浮動小数点値は既定の形式で出力されます。この形式では、精度は有効桁数を表します。ストリームは表示する値をその桁数に丸めるため、小数点の後にある先頭のゼロは有効桁数に含まれません。既定の形式では、値と精度に応じて通常表記または科学表記が選ばれます。精度を設定しても、単純に一定の桁数を超えた時点で科学表記に切り替わるわけではありません。

次の例を実行してください。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iomanip>
#include <iostream>

int main() {
    std::cout << std::setprecision(5);
    std::cout << 123.456 << '\n';
    std::cout << 0.0123456 << '\n';
    std::cout << 1234567.0 << '\n';
}
123.46
0.012346
1.2346e+06

最初の値は有効桁数5桁に丸められます。2つ目の値では、先頭のゼロは精度の桁数に含まれません。3つ目の大きな値は、既定の形式で科学表記になる場合があります。科学表記を明示的に指定するには std::scientific を適用します。この形式では、精度は小数点以下の桁数を表します。std::defaultfloat を使うと既定の形式に戻ります。

これらのマニピュレータはストリームの書式状態を変更します。std::setprecision で設定した精度は、別の精度を設定するまで、そのストリームへの後続の浮動小数点値の出力にも適用されます。std::setprecision を使うプログラムでは <iomanip> をインクルードしてください。

std::fixed で小数点以下の桁数を固定する

std::fixed と std::setprecision(n) を組み合わせると、小数点以下をちょうど n 桁で出力できます。価格や測定値など、小数点以下の桁数を揃えたい値に便利です。ストリームは必要に応じて表示値を丸め、小数部の桁数が足りない場合は末尾にゼロを補います。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iomanip>
#include <iostream>

int main() {
    const double price = 12.5;
    const double measurement = 3.14159;

    std::cout << std::fixed << std::setprecision(2);
    std::cout << price << '\n';
    std::cout << measurement << '\n';
}
12.50
3.14

std::fixed はそのストリームに続けて出力する浮動小数点値にも適用され、std::setprecision(2) で設定した精度も変更するまで有効です。既定の浮動小数点形式に戻すには std::defaultfloat を挿入します。その後の出力で必要なら、精度も改めて設定してください。

書式を整えた値を列に揃える

簡単な表を出力するには、std::setw、std::right、std::setfill、std::fixed、std::setprecision を組み合わせます。std::setw(n) で指定した幅は次に挿入する値だけに適用されるため、列の値ごとに呼び出してください。std::right は値の前に余白を置き、std::setfill は余白を埋める文字を指定します。小数点以下の桁数を固定すると、値の大きさが異なっても小数部の幅が揃います。そのため、同じ幅の欄に右寄せで出力すれば小数点の位置も揃います。

このセクションのコードと表示されるラベルや出力は英語のままです。

#include <iomanip>
#include <iostream>

int main() {
    const double values[] = {123.45, 2.5, 89.0};

    std::cout << std::fixed << std::setprecision(2)
              << std::right << std::setfill(' ');
    for (double value : values) {
        std::cout << std::setw(10) << value << '\n';
    }
}
    123.45
      2.50
     89.00

std::right、埋め込み文字、固定形式、精度は、後続の挿入にも適用されるストリーム状態として残ります。幅は例外で、次の書式付き挿入で消費されるため、値を出力するたびに std::setw を適用してください。最も幅の広い値が収まる欄幅を選びます。値が欄幅を超えても、切り詰められることはありません。