将int转换为short会产生意外结果

Tyr*_*gel 19 c# casting

我对C#中数字类型的丢失信息感到有些困惑.

当我这样做:

int x = 32780;
short y = (short)x;
Run Code Online (Sandbox Code Playgroud)

我有结果:-32756为y而不是预期的32767.为什么?怎么计算?

短期范围:-32768至32767范围:-2,147,483,648至2,147,483,647

Dan*_*zey 53

你似乎期待一种"四舍五入"的效果,而不是实际发生的事情,这是对数据的逐位重新解释.

在二进制中,x等于00000000000000001000000000001100,这是一个32位数,只有16位有效位.A short是16位有符号整数,使用二进制补码表示.

当你转换时,你的最后16位x被复制到y,给予1000000000001100.重要的是,这里的第一个数字是a 1.在二进制补码表示法中,这是-32756.你的号码没有被舍入 - 它被读作好像是16位.


Phi*_*idt 14

请阅读丹的答案,了解发生这种情况的"真实"原因,但这样就可以这样思考:当一个数字溢出其最大值时,它会回绕到最小值.所以,32780 - 32767 = 13-32768 (which is one of the 13) + 12 (the other 12) = -32756

  • @AndrasZoltan:二进制数通常表示方式的全部意义在于上述数学逻辑总是正确的吗?您可以同样争辩说,位模式只是上述逻辑的表示.对于大多数人来说,我怀疑溢出逻辑更容易理解. (5认同)

Jep*_*sen 6

可以说运行时添加或减去65536所需次数以获得short(System.Int16)类型范围内的数字.

如果您知道很多纯数学,而不是通过内部二进制表示(也很酷)来解释它,您可以从模运算中理解它.

为此,请将类型视为short模数为65536的整数,也写为ℤ/65536ℤ.ℤ/65536ℤ的每个成员都是同余类,即一组数字在除以65536时都具有相同的余数.现在,每个同余类都有不同成员("代表")的无限.如果您选择一个,则通过重复添加或减去65536来获得所有其他内容.

随着short数据类型,我们选择在区间的唯一代表-32768通过+32767.然后ushort是同样的事情,只有我们挑代表0通过65535.

现在关于ℤ/65536ℤ的很酷的事情是它形成了一个,其中我们有加法,减法乘法(但不是除法).实际上,在C#操作的unchecked上下文中short x,y;

(short)(x + y)
(short)(x - y)
(short)(x * y)
Run Code Online (Sandbox Code Playgroud)

完全对应于ℤ/65536ℤ中的算术.(我们要投回到short这里,因为技术上的C#定义了运营商只为int,uint,long,和ulong).

以相同的方式,sbytebyte可以被认为是环ℤ/256ℤ,intuint作为ℤ/4294967296ℤ,并longulong作为ℤ/18446744073709551615ℤ.

但请注意,因为这些模数不是素数,所以在环中不可能除法.例如,int X不满足

unchecked( 10 * X == 35 )   // integers Int32
Run Code Online (Sandbox Code Playgroud)

因此不清楚35/10应该是什么.另一方面,两个 X满足

unchecked( 10 * X == 36 )   // integers Int32
Run Code Online (Sandbox Code Playgroud)

但他们应该是36/10哪一个?

然而,正是一个int X

unchecked( 11 * X == 35 )   // integers Int32
Run Code Online (Sandbox Code Playgroud)

真正.我们运气好,因为11对于4294967296来说是比较优质的.解决方案X是1952257865(自己查一下),所以商数35/11在某个意义上就是数字X.

结论:整数运算+,-*C#可以简单地解释为ℤ/nℤ中的环运算.但/操作与戒指无关!