C++で浮動小数点型を扱うときのメモ(精度比較,精度設定)
(Qiitaを退会したため,同名の記事をQiitaからはてなに移行しました) AtCoderで問題を解いていたら、浮動小数点関連のC++の仕様でつまずいたのでメモ。
精度比較してみる
サンプルコード
#include<iostream> #include<cstdio> #include<iomanip> using std::cout; using std::cin; using std::endl; int main(void){ double pi=3.1415926535898; double kilopi=3141.5926525898; cout<<"pi---------------"<<endl; cout<<"cout "<<pi<<endl; cout<<"cout (set(10))"<<std::setprecision(10)<<pi<<endl; cout<<"cout (fixed,set(10))"<<std::fixed<<pi<<endl; printf("printf %f\n",pi); printf("printf (%%.10f) %.10f\n",pi); cout<<std::defaultfloat<<std::setprecision(6); cout<<endl; cout<<"kilopi---------------"<<endl; cout<<"cout "<<kilopi<<endl; cout<<"cout (set(10))"<<std::setprecision(10)<<kilopi<<endl; cout<<"cout (fixed,set(10))"<<std::fixed<<kilopi<<endl; printf("printf %f\n",kilopi); printf("printf (%%.10f) %.10f\n",kilopi); return 0; }
出力
pi--------------- cout 3.14159 cout (set(10))3.141592654 cout (fixed,set(10))3.1415926536 printf 3.141593 printf (%.10f) 3.1415926536 kilopi--------------- cout 3141.59 cout (set(10))3141.592653 cout (fixed,set(10))3141.5926525898 printf 3141.592653 printf (%.10f) 3141.5926525898
分かること
cout
はデフォルトで 「整数部、小数部合わせて6桁」printf
はデフォルトで 「小数部6桁」- マニピュレータ
std::setprecision(n)
を使うことで「整数部、小数部合わせてn桁」にできる - マニピュレータ
std::fixed
を使うことで「小数部n桁」にできる(小数部がn桁未満だった場合、0で埋められるみたい) - マニピュレータ
std::defaultfloat
を使うことでリセットできる(std::setprecision()
で指定したものはリセットされないみたい。要手動リセット) - マニピュレータを使う際は
#include<iomanip>
が必要
簡単なバグ回避策
一番最初にstd::cout<<std::fixed<<std::setprecision(10)
としておけば、浮動小数点型を出力する時に全て小数部10桁にできる、との情報をTwitterで教えてもらった。競技プログラミングをする限りではこれで全く問題ない。
参考資料
MaryCore 【C++】小数点の桁数を指定する方法と注意点【cout/iostream】 蒼色工房 printf出力書式まとめ