以下代码有什么作用?

时间:2011-02-28 17:30:18

标签: java

i = i + j ;
j = i - j ;
i = i - j ;

上面的代码是做什么的?有人可以用其他代码编写相同的操作吗?

日Thnx。

10 个答案:

答案 0 :(得分:14)

这是一种在不创建临时变量的情况下交换ij的值的技术。这是一种内存优化方式

如果您有兴趣了解其中的一些内容,我找到了一个关于交换价值的网站:

http://booleandreams.wordpress.com/2008/07/30/how-to-swap-values-of-two-variables-without-using-a-third-variable/

交换值的另一种方法是使用按位运算符Exclusive Or(XOR)

a = a ^ b

b = a ^ b

a = a ^ b

这种方式是我个人的最爱,因为从概念上思考会更有趣。整数是位组,(1和0)

64位整数有64“1和0”

1和0是二进制的。

1 = 1

10 = 2

11 = 3

100 = 4

101 = 5

111 = 6

这是二进制到十进制的示例。现在,按位运算符XOR的工作方式就像翻转开关一样。所以:

2 ^ 1 = 3:二进制:10 ^ 01 = 11

3 ^ 2 = 1:二进制:11 ^ 10 = 01 = 1

现在您已了解这一点,您可以看到如何与它交换变量。

让我们设置a = 3b = 2(二进制)并尝试

a = 100

b = 10

a = a ^ b :: a = 100 ^ 10 = 110

b = a ^ b :: b = 110 ^ 10 = 100

a = a ^ b :: a = 110 ^ 100 = 10

现在a = 10b = 100a = 2b = 3

欢迎来到位!

答案 1 :(得分:12)

它交换了ij。假设它们的初始值为ab,则行评估为:

i = a + b;
j = (a + b) - b; // = a
i = (a + b) - a; // = b

要回答你问题的第二部分,另一种选择(更有可能的是,在现实生活中采取的方法,非采访情况)看起来如下:

int tmp = i;
i = j;
j = tmp;

答案 2 :(得分:6)

临时变量交换

最常用的交换方法涉及使用临时变量:

T swap = i;
i = j;
j = swap;
swap = null; // or let it fell out of scope

Aritmetical swap

i = i + j ;
j = i - j ; // i + j - j = i
i = i - j ; // i + j - (i + j - j) = j

此hack仅在以下情况下有效:

  • ij整数,其总和介于2147483647和-2147483648之间。
  • ij ,其金额介于9223372036854775807和-9223372036854775808之间。

xor swap

有类似的xor swap hack

i = i ^ j;
j = i ^ j; // i ^ j ^ j = i
i = i ^ j; // i ^ j ^ i ^ j ^ j = j

它的变化很小:

a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j]; 
a[i] = a[i] ^ a[j]; 

此hack仅在以下情况下有效:

  • i != j,两个索引引用相同的元素,并且取消彼此取消。

答案 3 :(得分:3)

使用其他代码执行此操作的明显方法是:

const int tmp = i;
i = j;
j = tmp;

这假定类型为int。请注意,如果计算中存在整数上溢/下溢风险,则此交换技巧不安全。它也不是很清楚,阅读它的人需要非常难以理解正在发生的事情(或问别人)。

答案 4 :(得分:2)

它交换它们 - 但是如果你使用不同的变量名来保持清晰,那么告诉它更容易:

int originalI = ...;
int originalJ = ...;

int tmp = originalI + originalJ;
int newJ = tmp - originalJ;
int newI = tmp - newJ;

现在执行替换:

int originalI = ...;
int originalJ = ...;

int tmp = originalI + originalJ;
int newJ = originalI + originalJ - originalJ;
int newI = originalI + originalJ - (originalI + originalJ - originalJ);

...并简化:

int originalI = ...;
int originalJ = ...;

int tmp = originalI + originalJ;
int newJ = originalI;
int newI = originalJ;

...并删除临时变量:

int originalI = ...;
int originalJ = ...;

int newJ = originalI;
int newI = originalJ;

答案 5 :(得分:1)

它看起来像是交换ij

答案 6 :(得分:1)

它交换变量。

另一种方式:

i ^= j;
j ^= i;
i ^= j;

答案 7 :(得分:1)

假设ij是数字基元,假设运算符的运算方式与Java,C ++等相同,并假设运算符未重新定义,那么我们可以看一下像这样的代码行:

i = i + j;
j = i - j;
i = i - j;

这里,i成为两个变量的总和。但是,在第二行代码中,我们从该总和中移除j并将其分配给j。因此,我们可以将前两行减少到以下内容:

j = i;

变量j现在等于我们原来的i。但目前,i与其开头的价值不同。现在,i相当于原始两个值的总和。在下一行代码中,我们说:
i = i - j,伪代码相当于:i = originalSum - originalValueOf_i; //The original j

所以,基本上,所有原始代码都等同于交换例程,即:

tempVal = i;
i = j;
j = tempVal;


我们甚至可以尝试一个涉及正值和负值的例子,看看这是真的:

i = -24.3;
j = 10.4;
//Original code:
i = i + j; //i now equals -13.9
j = i - j; //j now equals -13.9 - 10.4, which is -24.3 (our original i value).
i = i - j; //i now equals -13.9 - (-24.3), which is 10.4 (our original j).


有人可能已经按照他/她所做的方式写了你发布的交换,以避免方法调用开销,声明新变量等等,但是如果你要交换很多值,那么使用你反复发布的代码就可以了得到icky。像上面所示的交换例程是相当普遍的。

答案 8 :(得分:0)

我得到了j的价值。并且j保持它的价值。

答案 9 :(得分:0)

它会切换ij

的值
i = i+j;
j = (original_i + j) - j = original_i;
i = original_i + original_j - original_i = original_j;

是的,还有其他方法可以this operation