Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么-1L*-9223372036854775808L==-9223372036854775808L_C#_.net_Math_F#_Binary - Fatal编程技术网

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”