我对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
Phi*_*idt 14
请阅读丹的答案,了解发生这种情况的"真实"原因,但这样就可以这样思考:当一个数字溢出其最大值时,它会回绕到最小值.所以,32780 - 32767 = 13和-32768 (which is one of the 13) + 12 (the other 12) = -32756
可以说运行时添加或减去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).
以相同的方式,sbyte并byte可以被认为是环ℤ/256ℤ,int和uint作为ℤ/4294967296ℤ,并long和ulong作为ℤ/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ℤ中的环运算.但/操作与戒指无关!