我想要使用仅有+=
和-=
运算符来交换两个变量的值,同时不使用临时变量。我知道标准的解决方案,例如:
a = a+b;
b = a-b;
a = a-b;
同时使用 xor
:
a ^= b;
b ^= a;
a ^= b;
但我不知道如何只使用+=
和-=
实现它。这可能吗?
我的同学们提供了一个很好的解决方案:答案是NO
我们把a
表示为(1 0)
,把b
表示为(0 1)
矩阵A
为
1 0
0 1
+=
和-=
表示将行相加或相减。这意味着行列式要么不改变符号,要么等于0
。最终矩阵为:
0 1
1 0
行列式等于-1
,所以你无法得到它。
更新:你有以下操作:
a-=a
。一行变成0
,因此det=0
a+=a
。那意味着将一行乘以2
,因此det A'= 2*det A
a+=b
。这意味着进行初等变换,不改变det
的值a-=b
。与3.
相同然后对b-=b
,b+=b
,b+=a
,b-=a
应用此证明。因此行列式没有改变其符号或者为0
更新2:正如@Tom在这里所说的:在C#中实现的示例:http://ideone.com/UzVLML。然而,在C语言中是不正确的:http://codepad.org/Rmhn9iqb。有人能澄清C和C#中b -= b += b
的区别吗?
b -= b += b
是未定义行为,因为在同一表达式中有两个对b
的赋值,且没有序列点介入。序列点是更新发生的标记,通常是;
、&&
、||
、bool ? true : false
文章中的?
、函数参数评估和从调用者到被调用者的控制传递之间的点、函数返回等等...只需搜索“序列点”与“未定义行为”,你就会明白。 - autistic a += b;
b -= b += b; // Negates b in most languages, but not in C
b += a;
a -= b;
b -= b += b;
是未定义行为,因为在引用 b
的对象时存在两个写入操作而没有中间的序列点。在 C++11(其中没有序列点)中,我认为赋值表达式中的赋值被排序在赋值表达式的值计算之前,所以我认为它是有效的。 - CB Baileyb += b
不是 void
类型,它具有 b
的类型,并且计算结果为 b
的赋值后的值。 - CB Baileyb -= b += b
仍然是未定义的。 -=
运算符左右两侧的求值相对于彼此是无序的,这意味着b
的修改(在右侧)和b
的值计算(在左侧)是无序的,从而导致未定义的行为。 - interjay a +=b;
b -=a;
b =-b;
a -=b;
b -= 2 * b
怎么样? - Toma+=b,a-=b,b+=a,b-=a
是可能的,但我无法证明。 - Toma+=a
和a-=a
,第一个可能会有用。 - medvedNick