C# 为什么-1L*-9223372036854775808L==-9223372036854775808L
我知道这与处理器处理溢出的方式有关,但我看不出来。与不同的负数相乘得到零或C# 为什么-1L*-9223372036854775808L==-9223372036854775808L,c#,.net,math,f#,binary,C#,.net,Math,F#,Binary,我知道这与处理器处理溢出的方式有关,但我看不出来。与不同的负数相乘得到零或-2^63: 在C#Interactive中: > return unchecked (-1L * -9223372036854775808L); -9223372036854775808 > return unchecked (-2L * -9223372036854775808L); 0 > return unchecked (-3L * -9223372036854775808L); -922337
-2^63
:
在C#Interactive中:
> return unchecked (-1L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-2L * -9223372036854775808L);
0
> return unchecked (-3L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-4L * -9223372036854775808L);
0
> return unchecked (-5L * -9223372036854775808L);
-9223372036854775808
> -1L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -2L * -9223372036854775808L;;
val it : int64 = 0L
> -3L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -4L * -9223372036854775808L;;
val it : int64 = 0L
在F#Interactive中:
> return unchecked (-1L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-2L * -9223372036854775808L);
0
> return unchecked (-3L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-4L * -9223372036854775808L);
0
> return unchecked (-5L * -9223372036854775808L);
-9223372036854775808
> -1L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -2L * -9223372036854775808L;;
val it : int64 = 0L
> -3L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -4L * -9223372036854775808L;;
val it : int64 = 0L
我之所以这样做,是因为它让我在F#中感到惊讶,直到我意识到F#默认在未检查的上下文中运行。尽管如此,我还是无法解释这种行为
我确实理解为什么9223372036854775807L+1L==-9223372036854775808L
,我只是不理解它与负数相乘,以及为什么它在0
(二进制全零)和-2^63
(二进制最高有效位1,剩余零)之间交替
有趣的是,这适用于,也就是说,由于
-1L*-9223372036854775808L==-9223372036854775808L
,因此-1L*-1L*-1L*-9223372036854775808L==-9223372036854775808L
和-1L*-1L=1L
,它表明恒等式定律仍然成立。你得到的答案都是正确的模2^64:也就是说,它们与数学上正确的答案相差2^64的倍数,这是正确截断答案的合理定义
我会用≅ 将模2^64全等的两个数关联起来。因此
- -1*-2^63=2^63≅ -2^63
- -2*-2^63=2^64≅ 0
- -3*-2^63=3*2^63=2^64+2^63≅ -2^63
等等。请注意,2^63和-2^63是全等的,但根据两个补码运算的约定,-2^63是可表示的。由于负数在2的补码中的表示方式,预期会出现这种行为 现在假设你有8位
1000 0000
这是-128
(签名)。它也可以翻译成128
(无符号)
将其乘以-1
如下
1000 0000 (*1)=> 1000 0000 (negate)=> 0111 1111 (+1)=> 1000 0000
1000 0000 (*2)=> 1 0000 0000 (negate)=> 1111 1111 (+1)=> 1 0000 0000
它以8位溢出,您再次得到-128
。(哦,别忘了这里可以得到的最大值是127
而不是128
。因为MSB用于符号)
将其乘以-2
如下
1000 0000 (*1)=> 1000 0000 (negate)=> 0111 1111 (+1)=> 1000 0000
1000 0000 (*2)=> 1 0000 0000 (negate)=> 1111 1111 (+1)=> 1 0000 0000
由于这个8位的值溢出,你会得到一个重复的
0
,但是有符号类型还有一个负值-这有一个有趣的特性,即abs(int)>0
并不总是真实的Windows计算器会给出相同的结果。不仅仅是QWord,还有任意大小的数字(即字、字节…)。我认为这与2的补码和它的计算方法有关。在2的补码中乘以-1不是取补码加1的方法吗?取补码得到的是9223372036854775807L
,加1得到的结果是你开始时的结果。注意(i)你的数量-9223372036854775808L实际上是-2^63,而不是-2^64。(ii)符号位中的-2^63实际上表示为1,其余的位表示为0;所有1的位模式都表示-1。@mike,说得对,你完全正确,现在已经修好了。你是说乘以2的求反步骤是1110 1111 1111吗?这似乎有道理,但这也是它这样做的原因吗?在数学中,可以有9
位。MSB将是第9位。获取111011111
没有多大意义,因为这些位不存在。修正了答案。对于处理器,我认为OF
和CF
标志将设置为1
。第9位就是不合适@AbelI明白,只是问一下,因为在之前的编辑中,你有3个小口。但是是的,有道理。载波位可能是在这些溢出情况下设置的。1000 0000“也可以转换为255”--作为无符号数,它将是128。这就是你的想法吗?哦,是的,谢谢你的更正。错过了“MikeSpivey”