2.4 実数の簡単な入出力と計算 -- 2次方程式を解く

今回も (C 流の scanf() & printf() ではなくて) ストリームを使って入出力をする。 ここで一つの困難が出現する。 数値計算プログラミングでは、結果を数値で出力する際に、 書式の指定をすることが必須であるが、 C++ で書式の指定をするのは思いの外面倒である。 C では %20.15f だけで済むことを一体どうやるのか、 以下のサンプル・プログラムを見てもらいたい。 世の中には、この理由から、C++ でプログラムを書く場合にも、 ストリームではなくて printf() を使って結果を出力する、 という人が結構いたようである。

(なお、「§2.10 入出力の書式 (とりあえずの例)」 も見よ。そちらの方が書いたのが新しい。)

(C の場合については、 「C言語これくらい覚えよう    §3.4 浮動小数点数の入出力と四則演算」 を見よ。)

quadratic_eq.cpp

/*
 * quadratic_eq.cpp
 */

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main(void)
{
  double a,b,c,D;
  cout << setprecision(15);
  cout.setf(ios::fixed, ios::floatfield);
  cout << "a,b,c: ";
  cin >> a >> b >> c;
  D = b * b - 4 * a * c;
  if (D >= 0)
    cout << setw(20) << (-b+sqrt(D))/(2*a) << ", "
         << setw(20) << (-b-sqrt(D))/(2*a) << endl;
  else
    cout << setw(20) << -b/(2*a) << "±"
         << setw(20) << sqrt(-D)/(2*a) << " i" << endl;
  return 0;
}

コンパイルと実行結果

oyabun% g++ -o quadratic_eq quadratic_eq.cpp
oyabun% ./quadratic_eq
a,b,c: 1 2 1
  -1.000000000000000,   -1.000000000000000
oyabun% ./quadratic_eq
a,b,c: 1 1 1
  -0.500000000000000±   0.866025403784439 i
oyabun%

率直に言って、 C++ のこのあたりの機能を設計した人間は馬鹿だったのだと思う。

(…乱暴なことを言うようだけれど、このせいで多くの人達に無用の混乱を与えて、 長い時間を浪費させていると思っている。C言語のやり方は、 Fortranのやり方を踏襲したもので、うまいやり方ではないけれど、 ほどほどの使い勝手だと思われる。)

参考: https://www.horstmann.com/ にある “The March of Progress”

1980: C
printf("%10.2f", x);
1988: C++
cout << setw(10) << setprecision(2) << fixed << x;
1996: Java
java.text.NumberFormat formatter = java.text.NumberFormat.getNumberInstance(); 
formatter.setMinimumFractionDigits(2); 
formatter.setMaximumFractionDigits(2); 
String s = formatter.format(x); 
for (int i = s.length(); i < 10; i++) System.out.print(' '); 
System.out.print(s);
2004: Java
System.out.printf("%10.2f", x);

(皮肉の説明をするのは無粋かもしれないけれど) Horstmann 先生の言いたいことは、 古い C で簡潔に出来ていたことが、 それから後に出た C++ や Java でどんどん複雑になって行った。 大した進歩だこと。 結局 2004年の Java では、C風のやり方が使えるようになった。 それ見たことか (最初からそうすれば良いのに)、ということだろう。



桂田 祐史