2018/07/09

[java]64bit値を扱うのにBigIntegerもある

Cからもらったunsignedな64bit値をビット演算するだけでよいかと思っていたら、数値としても扱う箇所があるのに気付いた。

うーん、uint64_tはプリミティブだから、Javaもlongで受け取って、中で数値に変換できないものか。。。


調べていると、BigIntegerというものがあった。
これを使って、引数はlongで受取り、中で16進数文字列に置き換え、それをBigIntegerにすればよさそうだ。

https://gist.github.com/hirokuma/f365c2a85dae3962ff3d5f19562b9029/a0e48bef4148691ce3fcc135c9911662ce21afc3

結果

long: -81985529216486896
long 2byte: -2
BigInteger: 18364758544493064720
BigInteger 2byte: 254

意味も無くビットシフトなんかさせてみたが、ちゃんと正の数として扱っている。

文字列は好きではないのだが、C側でやらなくてよいので、まあよかろう。

2018/07/07

[java]uint64_t相当のデータをビット演算したい

JNIを使って、CとJavaをつなごうとしている。
C側でuint64_tを使っている箇所があるので、Javaで何とかしなくてはならん。


Javaのlongは64bitなのだが、Javaにはunsignedがないので、たぶん最上位ビットが立ってたら負の数と思うだろう。
byteもそうだったし。

確認しておくべし。


longだけではなく、BigDecimalも使ってみよう。

https://gist.github.com/hirokuma/c8a67b1db8e44ce45236942088d81865/1aaa1e1893b3f83f9d1d14d494b1d4902da454ee

同じようなことをさせたいが、BigDecimalにビットシフトがないので、割り算で代用。
処理が遅くなりそうだが、まあ動作確認だからな。

結果

big decimal 2byte: fe
long 2byte: fffffffffffffffe

やはり、そうなるのか。
BigDecimalは演算してるから2byte分きっちりになったが、longはビットシフトで符号が引きずられたんだ。


そういえば、Javaには「>>>」があったな。

https://gist.github.com/hirokuma/c8a67b1db8e44ce45236942088d81865/0161393d1d388b1ad97754dbc84d3efb2eff8370

結果

big decimal 2byte: fe
long 2byte: fe

おお!
なんか、うれしくなりますな。


これはHEXで出しているから、変数として正負どちらになっているかわからん。
数字で出力させて確認。

BigDecimal : 正
longで>>:負
longで>>>:正

まあ、予想通りか。
当然だが、これをbyte型にキャストして代入すると、どれも負の数になる。