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

C# 将int转换为short会产生意外的结果,c#,casting,C#,Casting,我对C#中数字类型的丢失信息有点困惑 当我这样做时: int x = 32780; short y = (short)x; 我得到的结果是:y为32756,而不是预期的32767。为什么?这是如何计算的 短路范围:-32768至32767 int的范围:-2147483648到2147483647阅读Dan的答案,了解发生这种情况的“真实”原因,但可以这样想:当一个数字超出其最大值时,它会循环回到最小值。因此,32780-32767=13和-32768(这是13+12中的一个)和-32756您

我对C#中数字类型的丢失信息有点困惑

当我这样做时:

int x = 32780;
short y = (short)x;
我得到的结果是:y为32756,而不是预期的32767。为什么?这是如何计算的

短路范围:-32768至32767
int的范围:-2147483648到2147483647

阅读Dan的答案,了解发生这种情况的“真实”原因,但可以这样想:当一个数字超出其最大值时,它会循环回到最小值。因此,
32780-32767=13
-32768(这是13+12中的一个)和
-32756
您似乎期望的是“向下舍入”效应,而不是实际发生的情况,这是对数据的按位重新解释

在二进制中,
x
等于
00000000000000000000000001100
,这是一个只有16个有效位的32位数字。
short
是一个16位有符号整数,使用表示


转换时,
x
的最后16位将被复制到
y
,得到
10000000001100
。重要的是,这里的第一个数字是
1
。在二补表示法中,这是
-32756
。您的数字没有四舍五入,而是被读取为16位。

出现溢出。如果希望将数字限制为最大值,可以通过将整数与
short.MaxValue
进行比较来解决此问题:

short y;
if (x > short.MaxValue) {
    y = short.MaxValue;
} else if (x < short.MinValue) {
    y = short.MinValue;
} else {
    y = (short)x;
}
shorty;
如果(x>short.MaxValue){
y=短的最大值;
}else if(x
当您将x掷短时,您将得到溢出(即,分配的值超出了它所能处理的范围),并且您的值将表示为认为它将从最小值开始重新开始。正如您所说,short的最大值是32767,因此您的新值应该是:-32768+(32780-32768)=-32756


根据编程语言(可能还有编译器),您尝试执行的操作可能会导致异常,也可能不会。在C语言中似乎不是这样。

可以说运行时对
65536
进行加减的次数与获得
short
System.Int16
)类型范围内的数字的次数相同

如果你知道很多纯数学,而不是通过内部二进制表示法(这也很酷)来解释它,你可以从一个角度来理解它

对此,请考虑类型<代码>短<代码>为模65536的整数,也写成ℤ/65536ℤ. 每个成员ℤ/65536ℤ 是一个同余类,即当除以65536时具有相同余数的一组数。现在,每个同余类都有无限多个不同的成员(“代表”)。如果你选择了一个,你可以通过反复加或减65536得到所有其他的

使用
short
数据类型,我们通过
+32767
选择区间
-32768
中的唯一代表。那么
ushort
也是一样的,只是我们通过
65535
0
中选择代表

现在最酷的事情是ℤ/65536ℤ 它形成了一个函数,其中我们有加法、减法和乘法(但不是除法)。实际上,在
未选中的
上下文中,使用
短x,y,C#操作

(short)(x + y)
(short)(x - y)
(short)(x * y)
与中的算术完全对应ℤ/65536ℤ. (我们必须回到
short
,因为从技术上讲,C只为
int
uint
long
ulong
定义运算符)

同样地,
sbyte
byte
可以被认为是环ℤ/256ℤ, <代码>整数
uint
asℤ/4294967296ℤ, 和
long
ulong
asℤ/18446744073709551615ℤ.

然而,请注意,因为这些模不是素数,所以环中不可能除法。例如,没有
intx
满足

unchecked( 10 * X == 35 )   // integers Int32
因此不清楚35/10应该是什么。另一方面,两个
X
满足

unchecked( 10 * X == 36 )   // integers Int32
但是哪一个应该是
36/10

但是,只有一个
intx
可以

unchecked( 11 * X == 35 )   // integers Int32
对。我们很幸运,因为11是相对最好的4294967296。解决方案
X
是1952257865(自己检查),因此商
35/11
在某种意义上是数字
X


结论:C#的整数运算
+
-
*
可以简单地解释为ℤ/Nℤ. 但是
/
操作与环没有任何关系

你为什么期望32767?试试看会发生什么?更多的是关于位模式,但这是一个有用的答案,但这并不完全是为什么会发生的原因。@AndrasZoltan是的,我要走逻辑路线,而不是进入它后面的二进制。但这一点很好,至少应该是这样noted@AndrasZoltan:毫无疑问,二进制数通常表示方式的全部要点是,上述数学逻辑总是正确的?同样,您可以认为位模式只是上述逻辑的一种表示。对大多数人来说,溢出逻辑更容易理解,我怀疑。@Dan:不,它适用于任何东西。。。如果你数到163841,那么你会得到32767,然后再数到65536,你会回到32767(把所有的负数都算了一遍)。你再数到65536,你又回到了32767(总数是163839)。然后将另一个数到-32768,再将另一个数到-32767。计数总数为163841,最终结果与您的结果完全相同。您还应检查
x
,以确保完整性。在C#中,整数溢出