- 締切済み
clock関数を利用した時間計測法について
以下のソースコードについての質問です。 --- /* 文字列を1文字ずつ表示して後ろから1文字ずつ消去するのを繰り返す */ #include <time.h> #include <stdio.h> /*--- xミリ秒経過するのを待つ ---*/ int sleep(unsigned long x) { clock_t c1 = clock(), c2; do { if ((c2 = clock()) == (clock_t)-1) /* エラー */ return (0); } while (1000.0 * (c2 - c1) / CLOCKS_PER_SEC < x); return (1); } --- このコード中の while (1000.0 * (c2 - c1) / CLOCKS_PER_SEC < x); の箇所で、整数の 1000 ではなく、実数の 1000.0 を使う意味(メリット)は オーバーフロー対策の他に何かありますか? ありましたら教えてください。 また、整数の1000に比べ実数の1000.0を含む計算(浮動小数点演算)に 極端に時間がかかる環境の場合、 実数を使う方がsleep関数の精度が劣るデメリットがあると思いますが、 その他に実数を使う場合のデメリットはありますか? ありましたら教えてください。 (コードにおいて、clock_t型はunsignedと同義の場合もあれば signed long intと同義の場合もあると思いますが、どれもありうる(処理系依存)と考えてください。 CLOCKS_PER_SECも1000や1000000の場合もあると思いますが、どれもありうる(処理系依存)と考えてください。)
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- chie65536(@chie65535)
- ベストアンサー率44% (8802/19961)
>オーバーフロー対策の他に何かありますか? 無いですね。「オーバーフローしない為」に尽きます。 >CLOCKS_PER_SECも1000や1000000の場合もあると思いますが CLOCKS_PER_SECが1000000であり、clock_tがsigned long int(signed long intは符号付き32ビットとする)と同義の場合「1000 * (c2 - c1)」は「2.147483647秒」を超えるとオーバーフローします。 つまり「引数xに与えられるのは1~2147まで」になってしまいます。 うっかり「3秒待とう」と思って「3000」などを引数に与えて呼び出すと、sleep関数から永久に抜けて来ないでしょう。 なぜなら「1000 * (c2 - c1) / CLOCKS_PER_SEC」は「-2147~2147」の間をグルグルとループするだけなので、3000以上になる事は永久に無いからです。 引数が「unsigned long x」ってなっているなら、使う人は「60秒とかも大丈夫だよな」と思って、平気で「60000」などを引数に入れて呼ぶでしょう。 >どれもありうる(処理系依存)と考えてください。 「どの処理系でもちゃんと動く」のを考えるなら「引数xに与えられるのは1~2147まで」ってのは「問題外」ですね。 「処理系に依存しないで、どの処理系でも広範囲に使える」ようにするには「1000.0と書くしかない。他に選択肢は無し」です。
- jacta
- ベストアンサー率26% (845/3158)
> 1000 * (c2 - c1) / CLOCKS_PER_SEC > のときでもミリ秒(x)単位の計測はできると思いますが、 > 違うのでしょうか? すみません。勘違いでした。 そのとおりですね。
- jacta
- ベストアンサー率26% (845/3158)
clock_tおよびCLOCKS_PER_SECが整数型の場合、1000.0ではなく1000にすると、1秒未満は切り捨てられてしまいます。 結果として、ミリ秒単位の計測はできなくなります。 なお、clock関数が返すのはプログラムで使用したプロセッサ時間ですので、経過時間を計測するには不向きです。
補足
>clock_tおよびCLOCKS_PER_SECが整数型の場合、1000.0ではなく1000にすると、1秒未満は切り捨てられてしまいます。 >結果として、ミリ秒単位の計測はできなくなります。 とありますが、 1000 * (c2 - c1) / CLOCKS_PER_SEC のときでもミリ秒(x)単位の計測はできると思いますが、 違うのでしょうか? なぜなら、 1000.0 * (c2 - c1) / CLOCKS_PER_SEC の計算結果は実数に、 1000 * (c2 - c1) / CLOCKS_PER_SEC の計算結果は整数(小数以下切り捨て)になりますが、 比較対象のxは整数(unsigned long)なのでwhile文の判定結果は変わらないからです。 間違っていたらご指摘ください。
補足
解説いただきありがとうございました。 今後プログラムを読む際は、 なぜ実数(あるいは整数を)使っているのかという点に より注意を払っていこうと思います。