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


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
1021
セントラル64bitの15解決


セントラル

リンク

2006/10/21(Sat) 19:39:47|NO.3035

HSPで64Bit整数値は表現できますか?
足し引きできて、数値を文字列で表示できればいいんですが。



この記事に返信する


Irisawa

リンク

2006/10/21(Sat) 23:48:08|NO.3036

マシン語でやるか、拡張プラグイン(拡張型)を使うことになると思います。
表示だけなら


ddim v, 1 v = double(0xffffffff) + double(0xffffffff) mes "64bit 符号なし整数: " + strf("%I64u", v) mes "64bit 符号あり整数: " + strf("%I64d", v) mes "64bit 符号あり整数: " + strf("%I64i", v) stop

こんな感じでdouble型を%I64uや%I64dなどで変換すればできると思います。
(文字列なので整数演算はできません)



Irisawa

リンク

2006/10/21(Sat) 23:51:30|NO.3037

ちょっと、ちゃんと合っているかどうか(計算結果が正しいかどうか)は分かりませんが。
(^_^;



Irisawa

リンク

2006/10/22(Sun) 05:15:25|NO.3038

なんか、上記の答えでうまくいかないようなので四則演算の内、足し算と引き算のみと
雑用関数などをモジュール化してみました。


; LONGLONG 計算モジュール(四則演算と一部の雑用関数) #module "calc64" ; LONGLONG の上位 32 ビットを取得 #defcfunc HILONG double d, local tmp tmp = strf("%016I64x", d) return int("$" + strmid(tmp, 0, 8)) ; LONGLONG の下位 32 ビットを取得 #defcfunc LOLONG double d, local tmp tmp = strf("%016I64x", d) return int("$" + strmid(tmp, 8, 8)) ; LONGLONG を作成 #defcfunc MAKELONGLONG int p1, int p2, local v ddim v, 1 lpoke v, 4, p1 lpoke v, 0, p2 return v ; LONGLONG の計算実行(マシン語) #deffunc runmcn var v1, int func, double d1, double d2, local prm, local ret ddim v1, 1 prm = varptr(v1), LOLONG(d1), HILONG(d1), LOLONG(d2), HILONG(d2) ret = callfunc(prm, func, 5) return ; LONGLONG の足し算 #defcfunc add64 double d1, double d2, local func, local ret ; void add64(LONGLONG *llv, LONGLONG llv2, LONGLONG llv3) ; { ; *llv = llv2 + llv3; ; return; ; } func(0) = 0x8bec8b55, 0x558b0c4d, 0x144d0310, 0x1308458b func(4) = 0x08891855, 0x5d045089, 0x000000c3 runmcn ret, varptr(func), d1, d2 return ret ; LONGLONG の引き算 #defcfunc sub64 double d1, double d2, local func, local ret ; void sub64(LONGLONG *llv, LONGLONG llv2, LONGLONG llv3) ; { ; *llv = llv2 - llv3; ; return; ; } func(0) = 0x8bec8b55, 0x558b0c4d, 0x144d2b10, 0x1b08458b func(4) = 0x08891855, 0x5d045089, 0x000000c3 runmcn ret, varptr(func), d1, d2 return ret ; LONGLONG のかけ算(未完成) /* #defcfunc mul64 double d1, double d2, local func, local ret ; void mul64(LONGLONG *llv, LONGLONG llv2, LONGLONG llv3) ; { ; *llv = llv2 * llv3; ; return; ; } func(0) = 0xffec8b55, 0x75ff1875, 0x1075ff14, 0xe80c75ff func(4) = 0x00000000, 0x89084d8b, 0x04518901, 0x0000c35d runmcn ret, varptr(func), d1, d2 return ret */ ; LONGLONG の割り算(未完成) /* #defcfunc div64 double d1, double d2, local func, local ret ; void div64(LONGLONG *llv, LONGLONG llv2, LONGLONG llv3) ; { ; *llv = llv2 / llv3; ; return; ; } func(0) = 0xffec8b55, 0x75ff1875, 0x1075ff14, 0xe80c75ff func(4) = 0x00000000, 0x89084d8b, 0x04518901, 0x0000c35d runmcn ret, varptr(func), d1, d2 return ret */ #global v = MAKELONGLONG(0, 0xffffffff) mes strf("%I64u", add64(v, v)) v = MAKELONGLONG(0xff, 0xffffffff) mes strf("%I64u", sub64(v, MAKELONGLONG(1, 0))) ; mes strf("%I64u", mul64(v, MAKELONGLONG(0, 2))) ; mes strf("%I64u", div64(v, MAKELONGLONG(0, 2))) stop

ポイントはdouble型(64bit)を裏技的に使用しているところです。

かけ算と割り算は結構難しそうなので勘弁してください。
だれか代わりに修正してくれないかな〜。(^^ゞ

こんな事やるくらいならプラグイン作った方が早くて簡単なような気もしますけど。



Irisawa

リンク

2006/10/22(Sun) 06:30:00|NO.3039

上記モジュールをHSP開発Wikiにアップしてみました。

http://hspwiki.nm.land.to/?64bit%20%C0%B0%BF%F4%A4%F2%BA%C6%B8%BD



セントラル

リンク

2006/10/22(Sun) 08:36:59|NO.3040

わざわざありがとうございます!
double型を使う方法は思いつきませんでした。
しかし、一つ思ったのですが
そのLONGLONGと普通のint型を足し引きできないでしょうか?
度々すみません。



ny

リンク

2006/10/22(Sun) 08:37:08|NO.3041

もう少し具体的に何をしたいのか書いてもらえれば、よりよい方法が提案されるかもしれませんよ。
単に大きな値を使いたいのなら小数型をつかえば54bit整数とほぼ同じ範囲の整数を扱えますし、
blueleafさんの作成された多倍長整数型のプラグイン(http://hp.vector.co.jp/authors/VA034288/)
を使うのもいいと思います。
APIなどで64bit整数をつかうのであれば、いったん小数型や多倍長整数型に変換してから計算し、
再び64bit整数に戻すという方法が有効です。



セントラル

リンク

2006/10/22(Sun) 10:17:33|NO.3045

そうですね。具体的な方法は
ゲームのスコアに使いたいんです。
32bit整数値だと、足りなくなってしまうので
倍の64bitが使えたら…と思っています。



Irisawa

リンク

2006/10/22(Sun) 10:43:37|NO.3046

LONGLONG型は基本的にサイズが大きい(2倍)のLONG(int)型です。
それ以外の違いは基本的になく、LONGLONGとintを足す場合はintをLONGLONGに変換して
しまえばOKです。

上記のモジュールではMAKELONGLONGというint型の数値(p1とp2)を合成してLONGLONG型を
作成する関数を用意してありますのでそれを利用してください。

第1パラメータは上位32bit, 第2パラメータは下位32bitになるので第1パラメータを0に
すればint型の範囲を表現できます。



セントラル

リンク

2006/10/22(Sun) 10:58:17|NO.3047

そうですか。わかりました。
ありがとうございました!



ny

リンク

2006/10/22(Sun) 12:33:53|NO.3048

ゲームのスコアに使う程度なら小数型を使えば、難しく考えることなく約±9000兆の範囲の整数を誤差なしで扱えますよ。

a=9000000000000000.0 a=a+1 mes strf("%.0f",a)




セントラル

リンク

2006/10/22(Sun) 12:42:53|NO.3049

>nyさん
では、それをファイルに保存するには
どうすればいいのでしょうか?



ny

リンク

2006/10/22(Sun) 13:15:56|NO.3050

>では、それをファイルに保存するにはどうすればいいのでしょうか?
bsaveを使って小数型のままで保存する、もしくは文字列として保存するなどが普通かと思います。

a=9000000000000000.0 b=strf("%.0f",a) bsave "savefile1",a //小数型として保存 notesel b : notesave "savefile2" //文字列として保存 ddim c,1 : bload "savefile1",c //小数型としてロード notesel d: noteload "savefile2" : d=double(d) //文字列としてロード




セントラル

リンク

2006/10/22(Sun) 14:48:09|NO.3051

>nyさん
poke,wpoke,lpokeなどを使って1つのセーブファイルに
まとめているんですが、
小数を後から読み出せるようにバッファに保存できればいいんですが…。



ny

リンク

2006/10/22(Sun) 18:49:36|NO.3054

意味がよくわからないのですが。
小数型の大きさは8バイトなので、lpokeを2回使うかmemcpyを使えばいいだけなのでは?



Irisawa

リンク

2006/10/22(Sun) 23:58:28|NO.3057

あとは、負数を使用する必要がないようなら符号なし整数(unsigned int)を使用すれば
簡単です。
HSPの整数型(int)は符号あり整数(signed int)ですが、メモリなどの内部的には
unsigned intもsigned intも変わりません。
普通に演算して、表示するときだけ


buf = 0xffffffff mes strf("%u", buf) stop

このようにすれば、0〜4,294,967,295までの数値を表せます。



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