JavaScript/Elm ビット演算のときにはまったこと
結論 JavaScriptにおいて、>>>以外のビット演算は32ビット符号付き整数値として扱われる。 → 例えば&|^~の計算前に、オペランドに型変換が起こる(ソース)。 JSにおいて数字はNumberという型しかないが、ビット演算のときだけ32ビット整数値に変換されるっぽい JavaScriptにおいて、x >>> 0を使うと符号なし整数になる。 負数を2で割り続けても、コンピュータにおける2進表現にはならない。 これはすごく当たり前だった コンピュータにおける2進数表現にしたいなら,論理シフトを使うこと。 ElmはJavaScriptに変換されるので、上の事実はすべてElmでも当てはまる。 各種ビット演算は、JSの演算をそのまま使っているっぽい(ソース) 検証コード $ elm init src/MyBitwise.elmを作成し、内容を以下のようにする。 1 2 3 4 5 6 7 8 9 10 11 12 13 module MyBitwise exposing (..) import Bitwise toBinaryString : Int -> String toBinaryString x = let bit = Bitwise.and x 1 rem = Bitwise.shiftRightZfBy 1 x in if rem > 0 then (toBinaryString rem) ++ (String.fromInt bit) else String.fromInt bit elm replを起動し、試す。まず必要なモジュールをimportする。 $ elm repl > import Bitwise > import MyBitwise exposing (..) 232-1 = 4294967295を2進表示すると、1が32個並んだ数になる。32ビット整数の2の補数表現では、-1と4294967295は同じ表現方法になる。 > toBinaryString 4294967295 "11111111111111111111111111111111" : String > toBinaryString -1 "11111111111111111111111111111111" : String Bitwise.andの計算結果は符号付き整数値とみなされるので、以下では4294967295ではなく-1と出力される。 ...