ABC145 A - Circle
昨日はABC145お疲れ様でした。私は5完で終わってしまい、黄色返上しろって感情になりましたが、皆さんはいかがでしたでしょうか?
今回はそんなABC145の中で私が一番最後に通した、A - Circleの解説記事を書いていきたいと思います。
問題概要
整数が与えられる。半径の円の面積が半径の円の面積の何倍であるか求めよ。答えは制約の下では必ず整数になるので、整数として出力せよ。
制約
考察
半径の円の面積はであり、半径の円の面積はとなります。ここで次のようなコードを考えます。
#include <iostream> #include <cmath> int main(){ int r; std::cin >> r; const double pi = acos(-1.0); double circle_r = pi * r * r; std::cout << circle_r / pi << std::endl; }
投げてみます。
通っちゃったよ。以上です。
事の顛末
今更ABC-Aの解説記事など需要がありませんね?わかります。
なんでこんな記事を書いているかというお話をしたいと思います。
ふと競プロブログなら、解説記事くらい書きたくなることがあるだろうと思ったのですが、どうやって解説記事って書くんですかね?となりました。じゃあ簡単な問題でとりあえず形式だけ確かめてみようと思って書いてみました。
以上です。
閑話休題
わざわざ出力を整数にしろといっているのに、double型で出力して通ってしまいました。なぜでしょうか?
浮動小数点数は(整数)という形で保持されています。
C++でdouble型をcoutで出力する際、デフォルトでは10進数6桁分の精度で出力されます。つまり1.23456789は1.23457と出力され、123.456789は123.457と出力されます。ただし事はそう単純じゃなく、以下のようになっています。
入力 | 出力 |
---|---|
1.23456789 | 1.23457 |
123.456789 | 123.457 |
0.00123456789 | 0.00123457 |
123456789 | 123457e+08 |
0.00000123456789 | 1.23457e-06 |
1234 | 1234 |
100 | 100 |
e±nというのはという意味です。
このように基本的には6桁の精度で出力されるのですが、かなり複雑な表示のされかたをしていることがわかります。
C言語のprintfに出力で、フォーマット指定子としてgを選んだときの挙動となっているので、詳しくはそれを調べてみてください。
今回の出力としてありえる範囲は以上以下の整数です。coutは未満の整数は整数であるかのように表示されるので、今回は整数と同じフォーマットで出力されたためにACできたというわけです。
まともな解法
今回はこの解法でACできましたが、答えが整数になるなら、整数型で答えを保持するべきですし、今回のように小数で扱う必要がない問題では、整数の範囲で計算すべきです。浮動小数点数の保持の仕方を少し勉強すればわかることですが、小数は常に誤差の危険性と隣り合わせで必要のないときは基本的に使用を控えるべきです。
相似比の図形の面積比はですし、ですので、を計算すれば終わる問題ですね。次のように実装をすれば良いです。
#include <iostream> int main(){ int r; std::cin >> r; std::cout << r * r << std::endl; }
Submission #8505321 - AtCoder Beginner Contest 145
これで終わりです。