HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2012
0626
Cd3timer()11未解決


C

リンク

2012/6/26(Tue) 15:44:58|NO.47375

d3timer()は

Windows が起動してからの経過時間を ms (ミリ秒, 1/1000 秒) 単位で返します。
そうですが、返り値はintですので、2147483647msが最大値だと思います。

すると、これでタイマーを作ると、24d 20hr 31min 23.65sec が最大値だと思われます。

ここで、
1.d3timer()が24dを超えるとどうなるのか。
2.24dを超えるタイマーを作りたい時にはどうすればよいのか。

を教えてください。お願いします。



この記事に返信する


KA

リンク

2012/6/26(Tue) 16:01:42|NO.47376

>>1.d3timer()が24dを超えるとどうなるのか。

聞く前に自分で試しましょう。
その結果で対応方法も分かることが有ります。



test

リンク

2012/6/26(Tue) 16:22:27|NO.47379

自分で試すというのはたいへん素晴らしいことだと思いますが、今回の場合はさすがに酷だと思うので少しアドバイスをしたいと思います。


d3timerのヘルプをさらに熟読しましょう。
そうすれば、1.についてはその調べ方がわかるとおもいます。
あとはKAさんの言う通りです。
> その結果で対応方法も分かることが有ります。



C

リンク

2012/6/27(Wed) 05:12:04|NO.47388

こちらに書かれておりました。
http://msdn.microsoft.com/ja-jp/library/cc428795.aspx

これによると、

timeGetTime 関数で返される値は DWORD 値であることに注意してください。 戻り値は 0 ミリ秒から 2^32 ミリ秒の間を循環します。 2^32 ミリ秒は約 49.71 日にあたります。 計算に timeGetTime 関数の戻り値を直接使うようなコードでは、 特にコードの実行を制御する場合などに、問題が発生する可能性があります。 計算では常に、2 つの timeGetTime 関数の戻り値の差を使います。
だそうです。
すると、d3timer()はintを-2147483648~2147483647の範囲で循環するのでしょうか。

この場合、24dを超えるタイマーを作るには、どうしたらよいのでしょうか?

自分でも考えてみたのですが、上手くいきません。

#runtime "hsp3cl" #include "d3m.hsp" #include "longint.hsp" dim _co _co =0 _times =longint(strf("%u",d3timer())) if _times <1000 :_times+=1000 wait 100 repeat _timen =longint(strf("%u",d3timer())) if _timen <_times { _co++ } _timer =longint(_timen-_times)+(longint(4294967295)*_co) _timems =_timer\1000 _times =longint(_timer/1000)\60 _timem =longint(_timer/(1000*60))\60 _timehr =longint(_timer/(1000*60*60))\24 _timed =longint(_timer/(1000*60*60*24)) mes ""+_timed+":"+_timehr+":"+_timem+":"+_times+":"+_timems wait 50 loop



test

リンク

2012/6/27(Wed) 21:44:25|NO.47398

戻り値はDWORD(符号なし32bit整数)「戻り値は 0 ミリ秒から 2^32 ミリ秒の間を循環します。」と書いてあることから、
符号あり32bit整数であるHSPの側からみると、0から2147483647まで増加したあと次の瞬間-2147483648に飛び、その後-1まで増加した時点でDWORDの限界を迎え、0に戻ります。
したがって、「計算では常に、2 つの timeGetTime 関数の戻り値の差を使います。」に従えば、特別な処理が必要であるのは2147483647→-2147483468の瞬間のみであり、他は全て単調増加であることが分かります。

この瞬間は、前のd3timer()の値に対して新しいd3timer()の値が小さくなっているということで判定可能です。
この境目を超えた場合に何秒経過したか調べるには、

例えば前の値が「2147483644」であとの値が「-2147483640」だったとします。
このとき2147483644から正の値の限界である2147483647に到達するまでに3ミリ秒経過し、2147483647から-21474836478になる瞬間に1ミリ秒経過し、-21474836478から-2147483640になるまでに8ミリ秒経過したことから、合計12ミリ秒経過しているということが分かります。
というようにして調べることができます。

また、そんなに長い時間のタイマーを作ってどうしたいのかわかりませんが、経過した時間を2147483647ミリ秒を超えても保存しておくためには、そのようにlongintを使う方法や、あるいはもっと手軽な方法としては例えば86400000ミリ秒(一日)を超えた時点で「日数」を表す別の変数を1増やしてミリ秒のカウントのほうはそのぶん戻してしまうという方法をとれば、2147483647日(約588万年)カウントすることが可能です。



ヂオン

リンク

2012/6/28(Thu) 14:26:13|NO.47403

とりあえず hsp で 符号なし整数を比較する関数を作ってみました、
かなり無駄が多いですが、それなりに使えます。


#module //[戻り値] // -1 左辺が大きい // 0 同じ // 1 右辺が大きい #defcfunc cmpuslong int la_ , int lb_ , local rt_ // まず上位ワードを比較する wa = la_>>16 & 0xFFFF wb = lb_>>16 & 0xFFFF if(wa>wb){ rt_=-1 }else:if(wa<wb){ rt_=1 }else{ // 上位ワードがイコールである場合のみ下位ワードを比較する wa = la_& 0xFFFF wb = lb_& 0xFFFF if(wa>wb){ rt_=-1 }else:if(wa<wb){ rt_=1 } } return rt_ #global mes cmpuslong(0xFFFFFFFF/*int で言う -1*/,0)



ヂオン

リンク

2012/6/28(Thu) 14:49:08|NO.47404

余りに無駄が多いので、せめて機械語にしてみました、
理論上も、実際も、上記のスクリプトと比べて、三倍近く早いですが、やはり無駄が多いです。

C言語で比較式を書いてしまうのが一番いいでしょう。


#include "kernel32.as" #module cmp_usinglong #deffunc init_cmpuslong #define BUFFSIZE_CUSL 0x00000053 if(cusl==0){ // 下の配列はこのスクリプトを機械語化したもの ;int cul(DWORD a , DWORD b){ ;return (a==b ? 0 : (a>b ? -1,1));} cusl =0x81ec8b55,0x0000c4ec,0x57565300,0xff3cbd8d,0x31b9ffff,0xb8000000,0xcccccccc,0x458babf3,0x0c453b08,0x85c70c75 cusl(0x000a)=0xffffff3c,0x00000000,0x4d8b14eb,0x0c4d3908,0xe283d21b,0x01c283fe,0xff3c9589,0x858bffff,0xffffff3c,0x8b5b5e5f cusl(0x0014)=0xc35de5 VirtualProtect varptr(cusl),BUFFSIZE_CUSL,0x40,varptr(res) } return #define global ctype cmpuslong(%1=prm) callfunc(%1,varptr(cusl@cmp_usinglong),2) #global init_cmpuslong prm = 0xFFFFFFFF,0 cmpuslong()



KA

リンク

2012/6/28(Thu) 15:08:18|NO.47405

仕方ないので参考までに


#include "d3m.hsp" repeat cls A=d3timer() B+=abs(abs(A)-abs(C)) C=A mes ""+A mes ""+B wait 100 loop



KA

リンク

2012/6/28(Thu) 15:11:12|NO.47406

追記
上記Bの値を適当に処理して、適当に引いて下さい。



C

リンク

2012/6/29(Fri) 10:52:31|NO.47423

変なところでlongintがintに化けていたので修正してみました。
信じられないところで変わるので怖いです。

#runtime "hsp3cl" #include "d3m.hsp" #include "longint.hsp" dimtype _timen,vartype("longint"),2 dimtype _timer,vartype("longint") _timen.1 =longint(strf("%u",d3timer())) await 1 repeat _timen.0 =longint(strf("%u",d3timer())) while _timen.0 =_timen.1 wait 1 wend if _timen.0 <_timen.1{ _timer +=longint(4294967295)-_timen(1)+longint(1)+_timen(0) } if _timen.0 >_timen.1{ _timer +=longint(_timen(0)-_timen(1)) } _timems =longint(_timer\1000) _times =longint(_timer/1000)\60 _timem =longint(_timer/(1000*60))\60 _timehr =longint(_timer/(1000*60*60))\24 _timed =longint(_timer/(1000*60*60*24)) mes ""+_timed+":"+_timehr+":"+_timem+":"+_times+":"+_timems _timen.1 =_timen.0 await 1 loop



MillkeyWeler

リンク

2012/6/30(Sat) 07:06:33|NO.47433

質問者さんへアドバイス。
日付が変わったのを調べる方法は、単純に、ユリウス日の差を比較すればいい。
(BIOS の時刻を起動中に書き換えられれば、バグるけどね・・・)

あとは、testさんの方法かなー。正確に計測するのではなければ、HSP標準のGettime で日のms時間を
計測してて、前回の数値より低い結果になったら、日を加算してあげるって手も。

下記Gettime で計測サンプル

a=gettime(6)*1000+gettime(7) start_time=a last_time=a repeat await 10 a=gettime(6)*1000+gettime(7) if (last_time>a)&(of_flag=0) : last_time=0 : over_flow+(60000-start_time) : start_time=0 : of_flag=1 if (last_time>a)&(of_flag=1) : last_time=0 : start_time=0 active_time=(-start_time+a)+(over_flow) if active_time>=60000 : date_count+ : start_time=a : over_flow=0 : of_flag=0 last_time=a title "システム時刻 [ "+strf("%05d",a)+" ] : カウンタ時刻 [ "+strf("%05d",active_time)+" ] : 日付加算カウント [ "+strf("%05d",date_count)+" ]" loop

説明とかないけど、たぶん理解できると思う。
(もっとスマートにできる方いたら、改造よろしく)



ヂオン

リンク

2012/6/30(Sat) 16:47:00|NO.47439

すみません、なんだかすごく無駄なことをしていた気分です。
掲示板を乱してすみません。
レスを読み返して思いついたスクリプトを一つアップします。
31 ビット 目に マイナスの符号が立っていたら、それを折っているだけです。

#include "d3m.hsp" repeat c=d3timer() c^=(c&0x80000000) // これで 0 から int の最大値を繰り返す型と成ります。 await 30 loop



ONION software Copyright 1997-2023(c) All rights reserved.