質問編集履歴

1

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

2017/02/16 01:04

投稿

takey
takey

スコア312

test CHANGED
File without changes
test CHANGED
@@ -33,3 +33,151 @@
33
33
  このプログラムは、time.perf_counter()がオーバーフローしたら意図しない動作をしてしまいます。
34
34
 
35
35
  time.perf_counter()の最大値を知りたい(というか、とりうる値の範囲を知りたい)のですが、どうすればいいでしょうか?
36
+
37
+
38
+
39
+ [追記1]
40
+
41
+ 回答より、想像以上に早くオーバーフローしそうだということで、1分ごとのtime.perf_counter()の値をperf_counter.historyファイルに保存するコードを書きました。
42
+
43
+ ```python
44
+
45
+ #-*- coding:utf-8 -*-
46
+
47
+ import time
48
+
49
+ import datetime
50
+
51
+
52
+
53
+ while 1:
54
+
55
+ time.sleep(60)
56
+
57
+ d = datetime.datetime.now()
58
+
59
+ timestamp = "{}:{}:{}".format(d.hour, d.minute, d.second)
60
+
61
+ perf_c = str( time.perf_counter() )
62
+
63
+ text = "[{}]{}\r\n".format(timestamp, perf_c)
64
+
65
+
66
+
67
+ f = open("/var/tmp/perf_counter.history", "a")
68
+
69
+ f.write( text )
70
+
71
+ f.close()
72
+
73
+ ```
74
+
75
+
76
+
77
+ ↓perf_counter.history
78
+
79
+ ```
80
+
81
+ [17:19:6]5345.205548377
82
+
83
+ [17:20:6]5405.256627527
84
+
85
+ [17:21:6]5465.262088711
86
+
87
+ [17:22:6]5525.313487511
88
+
89
+ ...
90
+
91
+ (略)
92
+
93
+ ...
94
+
95
+ [8:40:40]60639.65602925
96
+
97
+ [8:41:40]60699.664641323
98
+
99
+ [8:42:40]60759.669727713
100
+
101
+ ```
102
+
103
+ ファイルを眺めた所、オーバーフローはしていませんでした。
104
+
105
+ そもそもtime.perf_counter()の型は何?と思い調べた所、float型でした。
106
+
107
+ ```
108
+
109
+ >>> import time
110
+
111
+ >>> type( time.perf_counter() )
112
+
113
+ <class 'float'>
114
+
115
+ ```
116
+
117
+ float型ということは、オーバーフローした後はマイナスの値を取る可能性があります。
118
+
119
+ ここで、pythonのfloat型の範囲がわからなかったので調べた所、次のサイトにヒントが書いてありました。
120
+
121
+ [文系のための「数値型」(2)](http://cis-jp.blogspot.jp/2012/12/blog-post_13.html)
122
+
123
+
124
+
125
+ > さて、次に実際の「有効桁数」と「精度」について見てみる。
126
+
127
+ Python の数値型は、C言語の数値型を借用していることはすでに述べた。
128
+
129
+ では、C言語のどの型を借用しているのか?
130
+
131
+ int ← C言語のlong型
132
+
133
+ long ← C言語には無い?
134
+
135
+ float ← C言語におけるdouble型
136
+
137
+ なんと、C言語のデータ型の大きい方だけを使っているようである。
138
+
139
+
140
+
141
+ pythonのfloat型はどうやらdouble型だそうです。
142
+
143
+
144
+
145
+ 混乱してきたので整理すると、
146
+
147
+ time.perf_counter()は
148
+
149
+ ・float型の数値を返す
150
+
151
+ ・pythonのfloat型はC言語のdouble型に当たる
152
+
153
+ ・ということは、値の範囲は-2^308~2^308(間違ってたらすみません)
154
+
155
+
156
+
157
+ time.perf_counter()のオーバーフロー後の動作が気になりますが、とりあえず「タイムアウト秒経過したら処理を抜ける」コードは次のように変更することで問題を回避できそうです。
158
+
159
+ ```python
160
+
161
+ import time
162
+
163
+
164
+
165
+ elapsed_sec = 0.0
166
+
167
+ pre_time = time.perf_counter()
168
+
169
+
170
+
171
+ while elapsed_sec <= timeout_sec:
172
+
173
+ (処理)
174
+
175
+ now_time = time.perf_counter()
176
+
177
+ if now_time > pre_time:
178
+
179
+ elapsed_sec += now_time - pre_time
180
+
181
+ pre_time = now_time
182
+
183
+ ```