C++の少数の出力結果が丸められてしまったのでsetprecisionマニピュレータをつかった。
はじめに
先日AtCoderさんのABC168に参加した時、
問題Cの出力結果の精度がどうしても欲しいところまで出なくて悩んでいた。
atcoder.jp
4.56425719433005553554 ...と割り切れない値のはずが、 4.56426 と表示されていた。
結論
setprecisionマニピュレータを使って解決した。
cout << fixed << setprecision(20) << getHoge() << endl;
コンテスト中に悩んでいたコード
仕様がわからずとりあえず精度を上げればなんとかならないかと考えて無意味にキャストしている。
#define ld long double ld getSqrtl(ld x1,ld y1,ld x2,ld y2){ ld x = x1 - x2; ld y = y1 - y2; ld ans = (ld)sqrtl( x*x + y*y ); return ans; } int main() { ld A,B,H,M; // 時間 分 cin >> A >> B >> H >> M; ld do2 = (ld)360.0 * ((ld)M/(ld)60.0); ld ra2 = do2 * ((ld)M_PI/(ld)180.0); ld x2 = B * cosl(ra2); ld y2 = B * sinl(ra2); ld do1 = (ld)360.0 * ((ld)H/(ld)12.0) + ((ld)30.0*((ld)M/(ld)60.0)); ld ra1 = do1 * ((ld)M_PI/(ld)180.0); ld x1 = A * cosl(ra1); ld y1 = A * sinl(ra1); cout << getSqrtl(x1,y1,x2,y2) << endl; }
出力結果
4.56426
出力の条件として、以下を満たす必要があるため不正解となってしまう。
setprecisionマニピュレータを使う
混乱しながらたどり着いた解決策がsetprecisionを使うことでした。
浮動小数点数を出力する精度を設定できる。
下記の例では少数第20位まで出力している。
cout << fixed << setprecision(20) << getSqrtl(x1,y1,x2,y2) << endl;
出力結果
4.56425719433005553554
おまけ
一回setprecisionすると次の出力では使わなくてもその出力結果になった。
cout << getSqrtl(x1,y1,x2,y2) << endl; cout << fixed << setprecision(20) << getSqrtl(x1,y1,x2,y2) << endl; cout << getSqrtl(x1,y1,x2,y2) << endl;
出力結果
4.56426 4.56425719433005553554 4.56425719433005553554
ABC167のCですごい時間使った。
— はこね (@hakone_san) May 17, 2020
C++の仕様の理解が足りなかった。
精度が足りなくて時間使ってたから悔しい。
けどsetprecisionを覚えた。 pic.twitter.com/bwvMQLWmy6