Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

(0xff - ...)みたいなことをやるなら、排他的論理和(XOR)を使うとメソッドチェインにできる

ZigBeeチェックサム等々、結果から0xffを減算する処理があります。
とはいえ、一回の減算のためにメソッドチェインを崩すのも気が引けます。
こういう場合、排他的論理和(XOR)を使えば引き続きメソッドチェインできます。

XOR

0xff - 0x12
#=> 237

これは

0x12 ^ 0xff
#=> 237

と等価です。
尻尾につくので、メソッドチェインを継続できます。

以前書いたZigbeeパケットのチェックサム

(str.delete("_").scan(/\w{2}/)[3..-2].map(&:hex).inject(&:+).&(0x00ff).^(0xff)).to_s(16)
#=> "b8"

と、メソッドチェイン式の書き方に改まりました。

速度的には遅い

と、見た目上のメリットがあるもの……
引き算と比較して15%程遅いみたいです。

require 'benchmark/ips'

def calc
  0xff - 0x12
end

def xor
  (0x12).^(0xff)
end

Benchmark.ips do |x|
 x.report( "calc" ) { calc }
 x.report( "xor" ) { xor }
 x.compare!
end
$ ruby xor.rb 
Calculating -------------------------------------
                calc   122.698k i/100ms
                 xor   117.831k i/100ms
-------------------------------------------------
                calc      6.759M (± 9.7%) i/s -     33.497M
                 xor      5.880M (±10.9%) i/s -     28.986M

Comparison:
                calc:  6758764.8 i/s
                 xor:  5879666.8 i/s - 1.15x slower

処理系次第では、XORの方が早かったりするのですが……残念。