質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

2回答

3107閲覧

javascriptでできるだけ正確なストップウォッチを作成するには

blendegg

総合スコア81

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

4クリップ

投稿2021/07/06 14:07

setintervalやsettimeout関数でストップウォッチを作成しようと思ったのですが、理屈はよくわからないのですが、これらは誤差が発生するようです。pcの性能によってカウントアップが遅れ、誤差が発生してしまうということでしょうか。
正確なストップウォッチを作成するにはどんな方法を使うと良いのでしょうか?

サーバがあればサーバの時刻を取るということも出来ると思います。
javascriptの場合はdate関数で時刻を取れますが、これもどれだけ正確なものかは分かりません。

Lhankor_Mhy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/07/07 00:51

「できるだけ」というのは非常に曖昧な表現です。 広く使われている太陽暦ですらうるう年を設けて調整してるくらいです。 誤差どれ位を許容するとか、アプリケーションとしての定義を確定しないことには答えは出ない気がします。
blendegg

2021/07/08 10:44

例えば、キッチンタイマーに使えるレベルの正確性さえアレば良いです。 何か重大な要件に使用するわけではないです。 また、javascriptで出来うる手法で、出来るだけ正確なものを知りたかったです。
guest

回答2

0

あらゆるイベントに timeStamp というプロパティがあり、これが 0.005ms 程度の精度だそうです。Date は 1ms 精度なので、timeStampのほうがかなり高精度になります。ストップウォッチ開始の click イベントなどでその timeStamp プロパティの値を保存しておき、ストップウォッチ終了時のイベントの timeStamp と引き算すればよいでしょう。

カウントアップの表示をしたい場合は、requestAnimationFrame() を用います。requestAnimationFrame() に渡したコールバック関数にも上記と同じ精度のタイムスタンプが渡されるので、ストップウォッチ開始時間との差を高精度で計算できます。

投稿2021/07/06 23:48

編集2021/07/06 23:52
int32_t

総合スコア21695

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blendegg

2021/07/07 03:32

ありがとうございます。requestanimationframeはまだ触れていませんが、timestampでの秒数の取得は上手くいきました。 後者についてわからなければ後に質問させていただきます。
hope_mucci

2021/07/07 04:54

ユーザーのアクション(start/stopボタンのクリック)に対しての精度を要求する場合は、おっしゃる通りイベントオブジェクトのtimestampで比較するのが最も良い方法だと思います。 requestAnimationFrameは存じませんでした。リフレッシュレート依存なのでsetIntervalより過度に負荷をかけないのがメリットという感じですね。
guest

0

setIntervalsetTimeout関数は、引数に指定した時間が最低限経過した後で指定のコールバック関数を実行するものです。
言い換えると、「xミリ秒経過してからコールバック関数を実行することを保証する」ということで、指定経過時間ピッタリに実行するわけではありません。必ず指定時間以上経過した後で関数が実行されます。

(setIntervalでカウントアップするよりは)正確にストップウォッチ機能を実装したいのであれば、Dataオブジェクトで開始時間を取得し、一定時間ごとにDate.now()で現在時刻を取得し、開始時間との差分をとるような実装にすれば良いかと思います。Date関数で取得する時刻精度はクライアント側に依存します。

投稿2021/07/06 17:42

hope_mucci

総合スコア4447

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blendegg

2021/07/06 21:38

回答ありがとうございます。 データ関数というのはシステム時刻(クライアントのos)から取得されているようですね。 これの正確性はかなり高いのでしょうか? ストップウォッチの作り方について、差分を利用するんですね。 疑問があるのですが、ストップウォッチのstartボタンを押した時と、stopボタンを押したときに現在時刻を取得し、差分を取得するとします。 ストップウォッチにはカウントアップの表示が必要ですが、stopボタンを押さないと差分は求められませんので、カウントアップの表示が出来ないのではないでしょうか?
hope_mucci

2021/07/07 04:48 編集

一般的なパソコンにおける時刻精度は、1.0^-5/秒ないし10^-4/秒程度と言われています(1秒につき0.01ms~0.1msくらいずれる)。秒だと分かりづらいかもしれませんが1日1秒1~8秒ほどずれる、程度の精度です。 時刻の積算に使われる水晶発振器という部品が熱に対し大きな影響を受けるので、使用環境によっては誤差が大きくなります。(興味があれば水晶発振器について調べてみてください) 例えば運動競技用でパソコンより正確な精度で記録を測定する場合、高品質な水晶発振器を使ったり光を使った計時方法になったりします。マラソンのような長時間にわたる計時ではパソコン程度の精度では1秒以上誤差が出る可能性があるのでより精緻な精度の製品が使われています。 この程度の誤差が許容できるかどうかは案件次第ではと思います。 int32_tさんの方法も「解像度が高い」だけで時間に対する精度としては同等と考えて良いかと思います(厳密には計時方法が異なるので完全に同等ではありません。また、解像度はパソコンの性能にも影響します) スタートボタン、ストップボタンを押した際の時刻を求めるならば、int32_tさんの方法の方が「プログラムコード的な誤差」は正確になると思います。
hope_mucci

2021/07/07 04:57 編集

計時中に差分を求める際は、setIntervalで「スタートボタンを押したときのタイムスタンプ」と「現在時刻」の差分を常に画面に更新し続ける方法で表現できるかと思います。Dateで行う場合はDate.now()をとり、DOMHighResTimeStampで行うのであればperformance.now()で取得できます。インターバルの都度新しい時刻オブジェクトを得るのでstart/stopのイベントほど正確な時刻差分の取得は期待できませんが、計時中は単なるアニメーションなので精度はそれほど問題ではないでしょう。 また、setIntervalの最小単位は10msです。int_32tさんの提唱するrequestAnimationFrameはディスプレイのリフレッシュレートに依存する仕様とされていますがPCの状態によりイベント発生頻度は上下するそうです。ウィンドウがアクティブかどうかでも変わります。ゲーミングディスプレイを接続していれば更新頻度が早くなるかもしれないし、ノートPCでバッテリー駆動していると更新頻度が下がるかもしれません。環境依存なので実際に実験して確かめてください。
blendegg

2021/07/09 01:58

どの方法もそれほど大差がないということですが、とりあえずtimestampでやってみます。どの程度の精度を求めるかですが、キッチンタイマーを作るのが目的ですので、1日に1秒程度の誤差なら問題にはならないと思います。
hope_mucci

2021/07/09 06:12

「精度」は2種類の文脈があります。「コンピュータが計算する1秒が実時間の正確な1秒からどのくらい誤差が出るか」と、「取得した時間に対する桁数」という意味の精度です。私は前者の意味でとらえて回答しました。int32_tさんは後者の意味でとらえて回答していると思います。 またキッチンタイマーであれば、ストップウォッチではなく(startとstopがある)経過時間を入力してスタートボタンを押し、入力した時間が経過したら停止するというものになるかと思います。setIntervalで経過を見る場合、ブラウザが最小化されていたり別のタブの画面が表示していたりするとイベント発生間隔が極端に落ちます。requestAnimationFrameの場合は全く更新されません。この点を考慮してください。実際に実験してみると面白いですよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問