質問するログイン新規登録

質問編集履歴

1

回答を参考にして、time\.perf_counter\(\)の値を検証しました。

2017/02/16 01:04

投稿

takey
takey

スコア312

title CHANGED
File without changes
body CHANGED
@@ -15,4 +15,78 @@
15
15
  pre_time = now_time
16
16
  ```
17
17
  このプログラムは、time.perf_counter()がオーバーフローしたら意図しない動作をしてしまいます。
18
- time.perf_counter()の最大値を知りたい(というか、とりうる値の範囲を知りたい)のですが、どうすればいいでしょうか?
18
+ time.perf_counter()の最大値を知りたい(というか、とりうる値の範囲を知りたい)のですが、どうすればいいでしょうか?
19
+
20
+ [追記1]
21
+ 回答より、想像以上に早くオーバーフローしそうだということで、1分ごとのtime.perf_counter()の値をperf_counter.historyファイルに保存するコードを書きました。
22
+ ```python
23
+ #-*- coding:utf-8 -*-
24
+ import time
25
+ import datetime
26
+
27
+ while 1:
28
+ time.sleep(60)
29
+ d = datetime.datetime.now()
30
+ timestamp = "{}:{}:{}".format(d.hour, d.minute, d.second)
31
+ perf_c = str( time.perf_counter() )
32
+ text = "[{}]{}\r\n".format(timestamp, perf_c)
33
+
34
+ f = open("/var/tmp/perf_counter.history", "a")
35
+ f.write( text )
36
+ f.close()
37
+ ```
38
+
39
+ ↓perf_counter.history
40
+ ```
41
+ [17:19:6]5345.205548377
42
+ [17:20:6]5405.256627527
43
+ [17:21:6]5465.262088711
44
+ [17:22:6]5525.313487511
45
+ ...
46
+ (略)
47
+ ...
48
+ [8:40:40]60639.65602925
49
+ [8:41:40]60699.664641323
50
+ [8:42:40]60759.669727713
51
+ ```
52
+ ファイルを眺めた所、オーバーフローはしていませんでした。
53
+ そもそもtime.perf_counter()の型は何?と思い調べた所、float型でした。
54
+ ```
55
+ >>> import time
56
+ >>> type( time.perf_counter() )
57
+ <class 'float'>
58
+ ```
59
+ float型ということは、オーバーフローした後はマイナスの値を取る可能性があります。
60
+ ここで、pythonのfloat型の範囲がわからなかったので調べた所、次のサイトにヒントが書いてありました。
61
+ [文系のための「数値型」(2)](http://cis-jp.blogspot.jp/2012/12/blog-post_13.html)
62
+
63
+ > さて、次に実際の「有効桁数」と「精度」について見てみる。
64
+ Python の数値型は、C言語の数値型を借用していることはすでに述べた。
65
+ では、C言語のどの型を借用しているのか?
66
+ int ← C言語のlong型
67
+ long ← C言語には無い?
68
+ float ← C言語におけるdouble型
69
+ なんと、C言語のデータ型の大きい方だけを使っているようである。
70
+
71
+ pythonのfloat型はどうやらdouble型だそうです。
72
+
73
+ 混乱してきたので整理すると、
74
+ time.perf_counter()は
75
+ ・float型の数値を返す
76
+ ・pythonのfloat型はC言語のdouble型に当たる
77
+ ・ということは、値の範囲は-2^308~2^308(間違ってたらすみません)
78
+
79
+ time.perf_counter()のオーバーフロー後の動作が気になりますが、とりあえず「タイムアウト秒経過したら処理を抜ける」コードは次のように変更することで問題を回避できそうです。
80
+ ```python
81
+ import time
82
+
83
+ elapsed_sec = 0.0
84
+ pre_time = time.perf_counter()
85
+
86
+ while elapsed_sec <= timeout_sec:
87
+ (処理)
88
+ now_time = time.perf_counter()
89
+ if now_time > pre_time:
90
+ elapsed_sec += now_time - pre_time
91
+ pre_time = now_time
92
+ ```