スリープを使い、経過した時間を1/50秒ずつ表示し続けてください
という問題を解いていて自分なりに考えてみたのですが微妙にずれて表示されてしまいます。
どこがおかしいのか教えていただけませんか。
#include "stdio.h"
#include "windows.h"
int main(void)
{
int t;
while(1){
t = GetTickCount();
printf(" %d 時間 %d 分 %d 秒 %d ミリ秒",
(t / 360000) % 24, (t / 60000) % 60, (t / 1000) % 60, t % 1000);
printf("\n");
Sleep(20);
}
for(; ;);
return 0;
}
よろしくお願いします
よろしくお願いします
-
first
Re: よろしくお願いします
すみません・・・。
学校のパソコンを使っているので、規制がかかっていてみることができませんでした。
詳しく説明すると20ミリ秒刻みで時間を表示したいのに、15ミリ秒ですとか、ばらばらな時間で表示されてしまいます。
おわかりいただけたでしょうか?
学校のパソコンを使っているので、規制がかかっていてみることができませんでした。
詳しく説明すると20ミリ秒刻みで時間を表示したいのに、15ミリ秒ですとか、ばらばらな時間で表示されてしまいます。
おわかりいただけたでしょうか?
- bitter_fox
- 記事: 607
- 登録日時: 15年前
- 住所: 大阪府
Re: よろしくお願いします
実行してみたところ確かになりますね。non さんが書きました:>15ミリ秒ですとか、ばらばらな時間
20ミリ秒より小さくなることがあるのですか?
22 時間 29 分 16 秒 324 ミリ秒
22 時間 29 分 16 秒 340 ミリ秒 *
22 時間 29 分 16 秒 355 ミリ秒
22 時間 29 分 16 秒 387 ミリ秒
22 時間 29 分 16 秒 402 ミリ秒 *
22 時間 29 分 16 秒 418 ミリ秒 *
22 時間 29 分 16 秒 449 ミリ秒
22 時間 29 分 16 秒 465 ミリ秒 *
22 時間 29 分 16 秒 480 ミリ秒 *
22 時間 29 分 16 秒 496 ミリ秒 *
22 時間 29 分 16 秒 527 ミリ秒
22 時間 29 分 16 秒 543 ミリ秒 *
22 時間 29 分 16 秒 558 ミリ秒 *
22 時間 29 分 16 秒 589 ミリ秒
・
・
・
MSDN さんが書きました: If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time.
If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on.
もしdwMillisecondsをシステムクロックの分解能よりも小さい値を指定した場合は、指定されている時間を満たさない場合もあるでしょう。
もしdwMillisecondsが二つの分解の間にある場合は、その間のいずれかのタイミングで復帰するでしょう。
となっていますので、もしシステムクロックの分解能が1/64secondの場合だと最大で15ミリ秒前後のずれが発生してしまう可能性があるでしょう。MSDN さんが書きました: 略. So if one tick is 1/64 second (15.625ms), 略.
略。もし1分解を1/64秒(15.625ミリ秒)とした場合は、略。
[hr][追記]
[イメージ]
Re: よろしくお願いします
無限ループに入る前に
timeBeginPeriod(1);
と書いてみてください。
タイマー精度を『1』ミリ秒にするおまじないです。
#無限ループなのでtimeEndPeriod書くとこない。
プログラムを変更しなくても、Windows Media Playerとか起動しておくだけでも精度が上がりますよ。
15ミリ秒の分解能だと、15ミリ秒ごとに15増えるわけなので、14ミリ秒目~30ミリ秒目の16ミリ秒でも30増えたことになってしまいます。
逆に15増えたばかりのときから数えると、15ミリ秒経過では20を超えてなくて、30ミリ秒経過で20を超えることになります。
timeBeginPeriod(1);
と書いてみてください。
タイマー精度を『1』ミリ秒にするおまじないです。
#無限ループなのでtimeEndPeriod書くとこない。
プログラムを変更しなくても、Windows Media Playerとか起動しておくだけでも精度が上がりますよ。
15ミリ秒の分解能だと、15ミリ秒ごとに15増えるわけなので、14ミリ秒目~30ミリ秒目の16ミリ秒でも30増えたことになってしまいます。
逆に15増えたばかりのときから数えると、15ミリ秒経過では20を超えてなくて、30ミリ秒経過で20を超えることになります。
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 15年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: よろしくお願いします
短いスパンで見るからずれるのであって、長い目で見ればどうでしょう?
例えば最初に時刻を記憶しておき、それを基準に「時刻-時刻」で後何ミリ秒待機すべきか計算してはどうでしょうか。
1ミリ秒の誤差が1000回あれば1秒の誤差になってしまいますが、
最初の時刻から計算すれば1000回計算しても、1回分の誤差で済むかと思います。
例えば最初に時刻を記憶しておき、それを基準に「時刻-時刻」で後何ミリ秒待機すべきか計算してはどうでしょうか。
1ミリ秒の誤差が1000回あれば1秒の誤差になってしまいますが、
最初の時刻から計算すれば1000回計算しても、1回分の誤差で済むかと思います。