導入
かなり厄介なので、正確な動きをかいておきます。
前提知識
・javascriptでは、数の型はNumberのみ。整数も小数も関係なくNumber型。
・Number型は、倍精度浮動点小数点数型であり、IEEE 754という規格が使われている。
・C#でいえばdouble。
・Number型の整数の精度は53bit。つまり、-2**53+1以上2**53-1以下の整数は正確に表記できる。(例えば、2*53+1のbit表記は2**53と同じ。)
・int32のbit表記には、補数表現が使われている。
javascriptのビット演算
ビット演算を行うときのみ、int32として扱われる。(>>>を含む計算は、uint32として計算されます。)
ビット演算が終了すると、int32(またはuint32)から通常のNumber型に戻る。
Number→intへの変換
①小数の場合は、近い整数に変換される。
②整数x を ((x % 2**32)+2**32) % 2**32に変換する。簡単に言えば、mod 2**32において等しい、0以上2**32-1の整数に変換する。
③その整数の2進数表記をint32とみなす。(演算が>>>の場合はuint32としてみなす。)
int32→Numberへの変換
・int32における整数nの値は、そのまま、Number型におけるnに変換される。
(bit表記は変わるが、数の世界では変化なし。)
整理
・>>>が含まれない場合、-2**31以上2**31-1以下の整数は、ビット演算の前と後では変化しない。
・-2**31-1以下の場合や2**31以上の整数の場合、値は変化する。
整数の精度に注意
-2**53以下の整数と2**53以上の整数を扱う場合、意図していない値になるので注意。
例えば、(2**53+1)^0は、上の変換通りに計算すると、変換後は1になりそうですが、実際は0になります。これは、2**53+1のbit表記が2**53である為です。
例
・-2*31^0は、-2**31 mod 2**32 = 2**31より2**31に変換され、これを2進数を表すと、100…00(32bit)になる。これをint32で解釈すると-2**31となるので、計算終了後はNumber型の-2**31になる。
・2**31^0は2進数で表すと、100…00(32bit)になる。これをint32で解釈すると、-2**31となるので、計算終了後はNumber型の-2**31になる。
・-2**31^0は、-2**31-1 mod 2**32=2**31-1より2**31-1に変換され、これを2進数で表すと、01111…1111(32bit)になる。これをint32で解釈すると、2**31-1となるので、計算終了後はNumber型の2**31-1になる。
・-1^0は、2**32-1に変換され、これを2進数で表すと、111…111(32bit)になる。これをint32で解釈すると、-1となるので、計算終了後はNumber型の-1になる。
・(2**31^0) + (2**31^0)は、-2**32になる。
参考文献
↓ かなり分かりやすいjavascriptの数値型に関する記事です。