LoginSignup
2
0

四則演算+αでビット演算を実装する

Last updated at Posted at 2023-12-23

概要

マインクラフトではscoreboardコマンドを利用して、符号付き32bit整数を扱うことができます。
しかし、scoreboard players operationコマンド(以下scoreboard operationコマンドと表記)には四則演算と剰余演算が実装されていますが、ビット演算は実装されていません。
これでは将来、scoreboardを用いてビット演算を行いたいときに困るので自前で実装をします。

目次

  • 環境
  • 実装

環境

Minecraft Java Edition 1.19.4

実装

NOT演算

符号付き整数では負数の表現に2の補数表現を利用しているため、以下のような等式が成り立ちます。

¬A=-(A+1)

したがって以下のように実装できます。

namespace:not.mcfunction
scoreboard players operation $_not_ output = $_not_ input
scoreboard players operation $_not_ output *= $-1 const
scoreboard players remove $_not_ output 1

AND演算

特にこれといったテクニックはなく、愚直に1ビットずつ順に最上位から最下位ビットまでをみて$A ∧ B$を計算します。
愚直に書いているのでコードは少し長くなります。

長いので折り畳み
namespace:and.mcfunction
scoreboard players set $_and_ output 0

execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players set $_and_ output -2147483648


scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 1073741824

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 536870912

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 268435456

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 134217728

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 67108864

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 33554432

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 16777216

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 8388608

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 4194304

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 2097152

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 1048576

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 524288

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 262144

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 131072

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 65536

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 32678

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 16384

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 8192

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 4096

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 2048

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 1024

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 512

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 256

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 128

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 64

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 32

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 16

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 8

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 4

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 2

scoreboard players operation $_and_ input1 += $_and_ input1
scoreboard players operation $_and_ input2 += $_and_ input2
execute if score $_and_ input1 matches ..-1 if score $_and_ input2 matches ..-1 run scoreboard players add $_and_ output 1

OR演算

ANDと同じように愚直に実装しても良いですが、小技を使って楽をします。
まず、ド・モルガンの法則を使ってこのように変形します。

A ∨ B = ¬(¬A ∧ ¬B)

すると、今までに実装したAND、NOTの組み合わせで表現できるのでこれらを利用して実装します。

namespace:or.mcfunction
scoreboard players operation $_not_ input = $_or_ input1
function namespace:not
scoreboard players operation $_and_ input1 = $_not_ output

scoreboard players operation $_not_ input = $_or_ input2
function namespace:not
scoreboard players operation $_and_ input2 = $_not_ output

function namespace:and

scoreboard players operation $_not_ input = $_and_ output
function namespace:not
scoreboard players operation $_or_ output = $_not_ output

XOR演算

XORも愚直に実装しても良いのですが、ここでも小技を使って楽をします。
まずXORを次のように分解します。

A ⊕ B = A + B - ((A ∧ B) >> 1)

+,-は通常の整数の加減、>>は左ビットシフトです。
また、左ビットシフトはscoreboard operationの演算にはありませんがここでは2の累乗をかけることと等価です。
したがって以下のように変形できます。

A ⊕ B = A + B - 2(A ∧ B)

この変形のイメージとしては$A+B$の繰り上がり部分を引いて$A ⊕ B$を得ている感じです。
この形ならば、さっきまでに実装したものとscoreboard operationコマンドだけで表現できるのでそれらを利用して実装します。

namespace:xor.mcfunction
scoreboard players operation $_xor_ output = $_xor_ input1
scoreboard players operation $_xor_ output += $_xor_ input2

scoreboard players operation $_and_ input1 = $_xor_ input1
scoreboard players operation $_and_ input2 = $_xor_ input2
function namespace:and

##左ビットシフト
scoreboard players operation $_and_ output += $_and_ output

scoreboard players operation $_xor_ output -= $_and_ output
2
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
2
0