5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptで1を31ビット左シフトするとマイナスになる

Posted at

JavaScript で 2^32 の値が必要になりました。そこで、1 << 32 を計算したところ、1 になってしまいました。試しに 1 << 31 を計算してみると、-2147483648 と負の値が返ることがわかりました。

以下のコードを書いてみると、1 << 30 までは期待通りの結果が得られているようですが、1 << 30 より大きい値は変な結果になってしまいました。

for (let i = 1; i <= 32; i++) {
    console.log(`1 << ${i}: ${1 << i}`);
}

console.log("1 << 32 << 32 << 32 << 32:", 1 << 32 << 32 << 32 << 32);
1 << 1: 2
1 << 2: 4
1 << 3: 8
1 << 4: 16
1 << 5: 32
1 << 6: 64
1 << 7: 128
1 << 8: 256
1 << 9: 512
1 << 10: 1024
1 << 11: 2048
1 << 12: 4096
1 << 13: 8192
1 << 14: 16384
1 << 15: 32768
1 << 16: 65536
1 << 17: 131072
1 << 18: 262144
1 << 19: 524288
1 << 20: 1048576
1 << 21: 2097152
1 << 22: 4194304
1 << 23: 8388608
1 << 24: 16777216
1 << 25: 33554432
1 << 26: 67108864
1 << 27: 134217728
1 << 28: 268435456
1 << 29: 536870912
1 << 30: 1073741824
1 << 31: -2147483648
1 << 32: 1
1 << 32 << 32 << 32 << 32: 1

Wandboxで実行する

原因

JavaScript ではビット演算は符号付き 32 ビット演算で行われます。

1 << 30

1 << 30 = 0b010000000000000000000000000000000

であり、 2147483648 と解釈されますが、1 << 31

1 << 31 = 0b100000000000000000000000000000000

となります。ここで、負の値は 2 の補数形式で表現されることに注意しましょう。最上位ビットが 1 のときは、負の値であることを表します。よって、 1 << 31-2147483648 と解釈されます。また、ビット演算は 31 ビットシフトまでしかサポートされていないようです。そのため、1 << 32 も正しく計算できませんでした。

ビット演算子 - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

JavaScript の数値型は大きな値も保持できる 1 ので適当にビットシフトしても大丈夫だろうと考えていましたが、大丈夫ではありませんでした...。

対策

べき乗演算子 ** を使いましょう。2 ** 32 (1 << 32) も正しく計算できます。

for (let i = 1; i <= 32; i++) {
    console.log(`2 ** ${i}: ${2 ** i}`);
}
2 ** 1: 2
2 ** 2: 4
2 ** 3: 8
2 ** 4: 16
2 ** 5: 32
2 ** 6: 64
2 ** 7: 128
2 ** 8: 256
2 ** 9: 512
2 ** 10: 1024
2 ** 11: 2048
2 ** 12: 4096
2 ** 13: 8192
2 ** 14: 16384
2 ** 15: 32768
2 ** 16: 65536
2 ** 17: 131072
2 ** 18: 262144
2 ** 19: 524288
2 ** 20: 1048576
2 ** 21: 2097152
2 ** 22: 4194304
2 ** 23: 8388608
2 ** 24: 16777216
2 ** 25: 33554432
2 ** 26: 67108864
2 ** 27: 134217728
2 ** 28: 268435456
2 ** 29: 536870912
2 ** 30: 1073741824
2 ** 31: 2147483648
2 ** 32: 4294967296

Wandboxで実行する

C++ では?

ちなみに、C++ でも試したのですが、1 << 31 は JavaScript と同様に -2147483648 になってしまいます!

#include <iostream>

int main()
{
    long long i = 1 << 31;
    std::cout << i << std::endl;
}
-2147483648

Wandboxで実行する

これは整数リテラル 1int 型であり、32 ビット符号付き整数型のためです。きちんと long long 型であることを明示しましょう。

#include <iostream>

int main()
{
    long long i = 1 << 31;
    std::cout << i << std::endl;
    
    long long j = 1L << 31;
    std::cout << j << std::endl;
}
-2147483648
2147483648

Wandboxで実行する

  1. 2 ^ 1024 まで保持できます: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_VALUE

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?