コードを書いていて, 値を入れ替えるときに,
C#は標準でswap関数は無いようなので,
if (from > to) // from > to だったら入れ替える { var temp = from; from = to; to = temp; }
と普通に書いていたら, 先輩が次のようにきれいにしてくれました!
static class math { public static void swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; } } ***** func(~~~~) { if (from > to) { math.swap(ref to, ref from); } .....
なるほど, たしかに, swapはこれからも使う気がするから, こっちのほうがいいしコードもきれいになった!(((o(*゚▽゚*)o)))
そして, ついでに XOR で swap する方法も教えてくれました!
a と b を swap したいとき,
a^= b^= a^= b;
で交換できるらしいです(((o(*゚▽゚*)o)))
いったいこれは何をしているのでしょうか!
a ^ b
は
a XOR b
を表しているそうです.
それで,
a ^= b;
は
a = a ^ b;
なので,
a ^= b ^= a ^= b;
⇔
a ^= b ^= (a ^= b);
⇔
a ^= (b ^= (a ^= b));
⇔
a ^= b ^= (a ^= b);
⇔
a ^= (b ^= (a ^= b));
なのです!
本当にこれでaとbが交換できるのでしょうか,
って, とても気になりました!
ためしてみます!
画像: http://hyperphysics.phy-astr.gsu.edu/hbase/electronic/xor.html
a : 1011
b : 1110
b : 1110
のとき,
a : 1011
b : 1110
a^b : 0101
b^(a^b): 1011 ← a だ!!(((o(*゚▽゚*)o)))
b : 1110
a^b : 0101
b^(a^b): 1011 ← a だ!!(((o(*゚▽゚*)o)))
おおお! たしかに b^(a^b) で a が取れています!
配列aのi番目とj番目を入れ替えることを考えてみるとどうでしょう?
この方法なんですが昔の時代のテクニックで今は使わないほうが良いようです。
エフェクティブJavaに書いてありました。(>_<)
なるほど…
ありがとうございます!
まあ仕事では使わない方がいいけどちょまどさんはCodeGolferなのでビット演算も一通り覚えておいた方がいいのではないでしょうか
以前kazu_yamamotoさんあたりがツイートしてらっしゃった気がしますが、
&a==&b のときにこれを使うとa,b両方の全ビットが0になるというバグがあるので使うべきではないです。
kazu_yamamotoさんあたりが以前にツイートしてらっしゃった気がしますが、
&a==&b の時にこれを使うとa,bの全ビットが0になるというバグがあるので使うべきではないです。
XOR交換云々については知識として知っておく程度でいいと思います。
実際のコードで使用するのはちょっと。。。
(可読性が悪い、最適化した際に効率が悪くなる、など)
昔の記事へのコメント、失礼しました。