从double类型向byte类型的强制转换是如何工作的?

7

我有一段代码,其中类型转换返回的值与较大的值相差很大。

static void Main(string[] args)
{
    double a = 345.09;
    byte c = (byte) a;
    Console.WriteLine(c);
    Console.ReadLine();
}

这将返回值为89。这背后的原因是什么?


8
请注意:345-256=89。 - Sweeper
4
一个字节只能包含256个值。之后,它会再次从0开始计数。其余部分基本上会“溢出”。 - Franz Gleichmann
这个回答解决了你的问题吗?如何在C#中将uint转换为int? - user12031933
3个回答

12

发生的情况是,当你将数字转换时,只有最后8位被取出。让我通过使用整数举个例子来解释。我使用整数是为了简单起见,因为如果你将double转换为非浮点数表示,小数部分无论如何都会被舍弃。

首先,我们看一下数字345的二进制表示:

string binaryInt = Convert.ToString(345, 2);
Console.WriteLine(binaryInt);

输出结果为:

1 0101 1001

现在我们只取最后8位,这是一个byte类型的大小:

string eightLastBits = binaryInt.Substring(binaryInt.Length-8);
Console.WriteLine(eightLastBits);

我们得到:

0101 1001

如果我们再次将其转换为byte,你会看到结果是89:

byte backAgain = Convert.ToByte(eightLastBits, 2);
Console.WriteLine(backAgain);

输出:

89

编辑:

正如InBetween指出的那样,int示例是真正的情况,也是在强制转换期间发生的。

查看将double转换为byte的实现:

/// <internalonly/>
byte IConvertible.ToByte(IFormatProvider provider) {
    return Convert.ToByte(m_value);
}

如果我们查看Convert.ToByte方法的实现:我们可以看到双精度浮点数首先被转换为整数:

public static byte ToByte(double value) {
    return ToByte(ToInt32(value));
}

3
我猜这就是 byte 类型长度范围的原因。二进制中的 255 等于 11111111(8 位数的最大值)。酷,今天我学到了一个新东西。每一天都是一个学校的日子。 - Prasad Telkikar
1
@PrasadTelkikar:没错。无符号字节(在C#中为byte)可以存储从0255的数字,有符号字节(在.net中为SByte)可以使用二进制补码存储从-128127的数字。 - Heinzi
1
一个完美的解释。学到了新东西。所有其他答案都有解释,但由于这个解释很深入,我会给予采纳答案的标记(这并不意味着其他答案是错误的)。 - Ankit Shah
1
+1. 使用 int 实际上并不是一个例子,它是真正发生的事情:(byte)a 在强制转换为 byte 之前调用了 a.ToInt32(),因此代码本质上是 (byte)(int)a - InBetween
@InBetween 好的,我做了一次编辑。你能看一下吗? - Mong Zhu
显示剩余2条评论

4

Byte 的范围 是从 0 到 255,你之所以得到了 89 的结果,是因为一旦超过 255,它会重新从 0 开始计数。即

byte c = (byte) a;  //345 - 255  (consider `0` as well)
Console.WriteLine(c); // i.e. 89

字节数范围背后的原因:

byte 存储8位数据。将 0000 00001111 1111 (8位二进制数据)的值分别定义为 byte 变量的 MinMax 值,因此在整数中它变成了 0255


2
请注意,这是为数不多的结果未指定的情况之一。
根据语言规范,省略不相关的情况:
对于从 floatdouble 转换为整数类型,处理取决于转换发生的溢出检查上下文(checked 和 unchecked 运算符):
在 unchecked 上下文中,转换总是成功的,并按以下方式进行。
如果操作数的值为 NaN 或无穷大,则[...]
否则,将源操作数向零舍入到最接近的整数值。如果此整数值在目标类型的范围内,则[...]
否则,转换的结果是目标类型的未指定值 可以推测,实现只是在转换为最接近的整数值后剥离了更高的位,仅保留了最低有效的 8 位,因为那很可能是此时最方便的事情。但请注意,根据此规范,对于此转换,089 一样有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接