Xor如何交换价值?

时间:2016-10-27 03:54:51

标签: java algorithm bitwise-xor

以下是原始代码:

public static String reverseString(String s){       
    if(s == null) return "";        
    char[] rev = s.toCharArray();
    int i = 0, j = s.length() - 1;
    while(i < j) {
        rev[i] ^= rev[j];
        rev[j] ^= rev[i];
        rev[i++] ^= rev[j--];           
    }       
    return String.valueOf(rev); 
}

我的问题是Xor如何在这里交换字符值,为什么需要rev [i ++] ^ = rev [j--]?

5 个答案:

答案 0 :(得分:13)

代码相当于

    rev[i] ^= rev[j];
    rev[j] ^= rev[i];
    rev[i] ^= rev[j];           
    i++;  j--;

最后一部分只需要递增i并递减j以进行下一次循环迭代。

至于为什么x ^= y; y ^= x; x ^= y可以交换值,我不知道为什么,但你可以通过查看所有四个来看到它适用于1位值可能性:

 start   after x^=y  after y^=x   after x^=y
x    y     x   y       x   y        x   y
0    0     0   0       0   0        0   0
0    1     1   1       1   0        1   0
1    0     1   0       1   1        0   1
1    1     0   1       0   1        1   1

因此,您可以看到,在所有情况下,都会交换xy位。当语句应用于更大的整数时,^运算符并行处理所有位,因此最终结果是每对位都被交换,即整个值都被交换。

答案 1 :(得分:2)

XOR运算符具有这个非常独特的运算符,它充当不等式检测器意味着只有当两位不同时,结果才会 1 结果是 0

现在以A^Bith位1为例,这意味着AB的第i位不同。其中一个是1,另一个是0

现在我们执行此操作(A^B)^B时,如果B中的第i位为0,那么我们将获得1 1^0 = 1,这是ith等于A(A^B)^A = 0中的ith位,B中的1位。

同样,当第i位为B A0ith时,再次进行交换。

同样的逻辑适用于A^B0位为A^B的情况。你可以很容易地弄清楚它。

很容易看到交换是如何发生的,当您使用' xor原始数字时,您会得到另一个数字,因为交换每个相应的位

答案 2 :(得分:0)

以下例程应该交换ab

的值
a = a ^ b
b = b ^ a
a = a ^ b

让我们分析看看互换的工作原理和原因。

为此,我们不要交换值,而是将它们存储在单独的变量中,这样我们就可以看到究竟发生了什么。

a0 = a ^ b
b1 = b ^ a0
a1 = a0 ^ b1

使用XOR的以下属性简化方程式。查看XOR Properties@Wikipedia以获取参考

  1. 可交换(a ^ b == b ^ a
  2. associative(a ^ (b ^ c) == (a ^ b) ^ c
  3. a ^ a == 0
  4. 0 ^ a == a
  5. a0 = a ^ b                      // Equation #1
    b1 = b ^ a0
    a1 = a0 ^ b1
    
    b1 = b ^ a0                     // Equation #2
       = b ^ (a ^ b)                // Using Equation #1
       = b ^ (b ^ a)                // Property #1
       = (b ^ b) ^ a                // Property #2
       = 0 ^ a                      // Property #3
       = a                          // Property #4
    
    a1 = a0 ^ b1
       = a0 ^ (b ^ a0)              // Using Equation #2
       = (a ^ b) ^ (b ^ (a ^ b))    // Using Equation #1
       = (b ^ a) ^ (b ^ (b ^ a))    // Using Property #1
       = (b ^ a) ^ ((b ^ b) ^ a)    // Using Property #2
       = (b ^ a) ^ (0 ^ a)          // Using Property #3
       = (b ^ a) ^ a                // Using Property #4
       = b ^ (a ^ a)                // Using Property #2
       = b ^ 0                      // Using Property #3
       = b                          // Using Property #4
    

    如您所见,b1现在包含a的原始值,而a1包含b的原始值,即{{1}的值1}}和b交换

    总之,a只是一个惯用的表达,其中没有什么神奇之处:)

    相同的简单英语解释

    XOR在操作数位不相似时设置位,否则重置位

    让我们通过一个例子来讨论发生的转变。为此,我们将以下数字(以二进制形式)分配给变量。

    a^=b;b^=a;a^=b

    第1步a = 1 1 0 0 b = 1 0 1 0 //创建一个面具

    a = a ^ b

    想象一下,a = 0 1 1 0 b = 1 0 1 0 的新值是一个掩码,用于生成给定a的{​​{1}}的旧值或生成给定a的{​​{1}}的旧值。

    第2步b //使用掩码和原始值b

    恢复a的原始值
    b = b ^ a

    由于a仍然保留/未触及,我们可以使用掩码恢复b的原始值 - 这就是我们在此步骤中所做的

    第3步 a = 0 1 1 0 b = 1 1 0 0 //使用掩码和原始值b恢复a的原始值

    a = a ^ b

    现在我们在变量b中拥有a的原始值,因此我们可以使用相同的掩码来恢复a = 1 0 1 0 b = 1 1 0 0 的原始值。我们现在可以覆盖蒙版,因为在这一步之后我们不需要蒙版。

答案 3 :(得分:0)

如果您同意y == (x^y)^x == x^(y^x),那么您就有了答案。

在您提供的代码中考虑循环体的抽象版本:

a = a ^ b
b = b ^ a
a = a ^ b

现在重命名一个值以澄清发生了什么:

a_xor_b = a ^ b
b = b ^ a_xor_b // Now b is the original a because b^(a^b) == a!
a = a_xor_b ^ b // Now a is the original b because (a^b)^a == b!

现在请注意,如果a_xor_b是同一个变量a,则代码可以正常工作。

答案 4 :(得分:0)

首先考虑一种交换两个数字值ab的不同(但密切相关)方式可能更容易:

a =  a + b;
b =  a - b;
a = -b + a;

这既适用于纯任意精度数,也适用于模数为N的整数(当它们变得太大或太小时会包围整数,就像它们在Java中一样)。

要以数学方式分析,我们应该在每次值发生变化时分配一个新符号,以便=可以表示数学相等而不是赋值。那么,这只是一个基本的代数问题。

a1 = a0 + b0
b2 = a1 - b0 = (a0 + b0) - b0 = a0
a2 = -b2 + a1 = -(a0) + (a0 + b0) = b0

XOR怎么样?解释XOR的一种方法是将其视为无需携带的二进制加法。然后,使用XOR执行交换等同于执行&#34;添加交换&#34;然而,可以简化表达式,因为除了模2之外,每个数字都是它自己的逆(等效地,加法和减法是相同的)。这(具有可交换性)让我们熟悉:

a = a ^ b;
b = b ^ a;
a = a ^ b;

一般来说,&#34;添加交换&#34;上面可以用任何数学group来执行(即使它是非交换的 - 基本上只需要相关性和反转)。另一种思考XOR的方法就是它在n位整数上引入一个组结构,因此交换就像在任何组中一样工作。