0
0

ビット否定を使用した加算・減算【JS】

Posted at

はじめに

ビット否定演算子~を使用した加算・減算ができるようです。

ビット否定演算子

MDNでは以下のように定義されています。
(日本語版ではBigintについての記載が不足しているため、英語版を引用)

The bitwise NOT (~) operator returns a number or BigInt whose binary representation has a 1 in each bit position for which the corresponding bit of the operand is 0, and a 0 otherwise.

簡単な訳

  • ビット否定演算子~は、number or Bigintを返します
  • 各bit部分が0のときは1、それ以外では0を返します

実例

理解には、実例を見るのが速いでしょう。

「ビット否定」という名称ですが、「ビット反転」と呼ぶべき挙動です。

9 (base 10) = 00000000000000000000000000001001 (base 2)
               --------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)
  • base 10は10進数のこと
  • base 2は2進数のこと
  1. 10進数の9 = 2進数の00000000000000000000000000001001
  2. ~9 = 00000000000000000000000000001001を反転させたもの
  3. = 11111111111111111111111111110110 = -10

※ここでの負数の扱いは、以下のページで「2の補数表現」と紹介されているものです。


以上の例では、~9-10になりました。この例以外でも、~n-(n+1)を返します。

console.log(~-4) //3
console.log(~0) //-1
console.log(~1) //-2
console.log(~-1) //0

ビット否定を使用した加算・減算

本題です。「~n-(n+1)を返す」仕様を応用して、加算・減算ができます。

function add(n) {
  return -~n
}

function subtract(n) {
  return ~-n
}

console.log(add(4)) // 5
console.log(subtract(0)) // -1

この手法は、単に技術的なおもしろさだけでなく、以下の利点があります。

  • オペランドが一つであり、コードが短い
  • undefined0として扱うことができる

undefined0として扱う

これは、-~と同じく「コードが短い」というメリットを持つ++と比較した時のメリットです。

以下の例では、arr[1]が存在しませんが、それを呼び出して処理をしています。
++を使用する場合、add3のようにn++ | 1という書き方をすれば解決できますが、-~は、この場合分け記述を必要としません。

function add(n) {
  return -~n
}

function add2(n) {
  return n++
}

function add3(n) {
  return n++ | 1
}

let arr = []

console.log(add(arr[1])) // 1
console.log(add2(arr[1])) // NaN
console.log(add3(arr[1])) // 1

おわりに

面白いだけでなく、実用的な面もある興味深い手法でした。
ただ、一般的には可読性が低いと言って良いでしょう。その点は注意が必要です。

この記事は以下のコメントをもとに作成しました。コメントありがとうございました。

0
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
0
0