オーバーフローとシフト演算

こんにちは 村上です。

先日Javaで書かれたロジックをRubyに移植しようとしてハマった内容です。

オーバーフロー

問題です。下記の実行結果はなんでしょう?

JavaとRubyでは結果が異なります。

Java

Ruby

お気づきの通りJavaはオーバーフローを起こします。
Rubyの場合は型変換が行われ、自動でより大きい型に変換されます。
(実際「2147483648」ぐらいでは型変換が行われませんが)

オーバーフローを意図的に起こしているようなロジックではこの部分でハマります。

シフト演算

続きましてシフト演算です。
これもオーバーフローを起こす場合はJavaと結果が異なりますが、もう一つ異なることがあります。

右論理シフト

Javaには右シフトする場合、算術シフトと論理シフトがあります。

簡単に言うと符号ビットをシフト対象にするかしないかの違いですね。

Rubyには右論理シフト(>>>演算子)がない!?

Rubyの場合

となり論理シフトができません。

おそらく、Javaの場合は最上位bitが符号bitになるんで、シフト対象がわかりますが、Rubyの場合は最上位bitがわかりません。
たぶん型という概念がないんで、最上位bitが32bit目なのか、64bit目なのがわからないんでしょう。

Javaのコードを移植する場合は右論理シフトも要注意です。

どう対応したか?

簡単です。
オーバーフローさせてしまえばいい。
シフトの時は最上位bitを反転させてやればイイんです。

オーバーフロー

右論理シフト

かなり無理矢理ですね。。。
でもこんな感じでRubyへの移植は無事完了しました!!

Comments are closed, but you can leave a trackback: Trackback URL.