C++ iostream での浮動小数点数フォーマット

C++リハビリ中.

本格的に使っていたのは,1993年ごろなので,もう15年も前. 完全に浦島太郎だ. あの頃は,テンプレートもまともに動かなかったものだなあ. namespaceもなかったし.

わざわざ使わなくてもいい iostream を無理矢理使ってみているのだけど,浮動小数点数の出力フォーマットの制御ができない. printfなら簡単なのに. 昔はフォーマット制御ができる拡張があったような気がするのだけど,obsoleteになったらしい.

boostというライブラリ集を使うといいらしいのだけど,このためだけに導入というのもちょっと.

調べてみると,setf でフラグを指定して,setprecisionを組み合わせると,ある程度は制御できることがわかった. floatfieldで指定できるのは,fixed,scientificの2種類. これらはどれもデフォルトの状態とは違うので,デフォルトにもどすには,fmtflags(0) でクリアしてやらなければならないようだ. テストコード.

#include <iostream>
#include <iomanip>

void output() { 
  double d = 1234567890.0123456;
  for (int i = 5; i < 15; i++)
	  std::cout << std::setprecision(i) << d << std::endl;
  std::cout << std::endl;
}

main(){
  output(); // デフォルト

  std::cout.setf(std::ios_base::fixed,std::ios_base::floatfield);
  output(); // fixed

  std::cout.setf(std::ios_base::scientific, std::ios_base::floatfield);
  output(); // scientific

  std::cout.setf(std::ios_base::fmtflags(0), std::ios_base::floatfield);
  output(); // デフォルト
}

実行結果

1.2346e+09
1.23457e+09
1.234568e+09
1.2345679e+09
1.23456789e+09
1234567890
1234567890
1234567890.01
1234567890.012
1234567890.0123

1234567890.01235
1234567890.012346
1234567890.0123456
1234567890.01234555
1234567890.012345552
1234567890.0123455524
1234567890.01234555244
1234567890.012345552444
1234567890.0123455524445
1234567890.01234555244446

1.23457e+09
1.234568e+09
1.2345679e+09
1.23456789e+09
1.234567890e+09
1.2345678900e+09
1.23456789001e+09
1.234567890012e+09
1.2345678900123e+09
1.23456789001235e+09

1.2346e+09
1.23457e+09
1.234568e+09
1.2345679e+09
1.23456789e+09
1234567890
1234567890
1234567890.01
1234567890.012
1234567890.0123

setprecisionの意味が,モードによって異なる. fixedモードでは,n浮動小数点以下の桁数を指定していることになる. scientificモードでは,指数部の浮動小数点以下の桁数になる. デフォルトモードの挙動は正直いってよくわからない. なんなんだ.