我最近一直在玩一些字节数组(处理灰度图像).一个字节的值可以是0-255.我正在修改字节,并遇到了我分配给字节的值超出字节范围的情况.它正在为我正在玩的图像做出意想不到的事情.
我写了一个测试,并了解到该字节仍然存在.例:
private static int SetByte(int y)
{
return y;
}
.....
byte x = (byte) SetByte(-4);
Console.WriteLine(x);
//output is 252
Run Code Online (Sandbox Code Playgroud)
有一个结转!当我们走另一条路时,就会发生这种情况.
byte x = (byte) SetByte(259);
Console.WriteLine(x);
//output is 3
Run Code Online (Sandbox Code Playgroud)
我希望它在第一种情况下将其设置为255,在第二种情况下将其设置为0.这个结转的目的是什么?是不是因为我正在投射这个整数赋值?什么时候在现实世界中有用?
byte x = (byte) SetByte(259);
Console.WriteLine(x);
//output is 3
Run Code Online (Sandbox Code Playgroud)
SetByte结果的强制转换是将模256应用于整数输入,有效地丢弃超出一个字节范围的位.
259%256 = 3
原因:实施者选择仅考虑8个最低有效位,忽略其余位.
编译C#时,您可以指定是以编号还是未选中模式编译程序集(默认情况下未选中).您还可以通过使用checked
或unchecked
关键字使代码的某些部分明确.
您当前正在使用unchecked
忽略算术溢出并截断值的模式.该checked
模式将检查可能的溢出并在遇到它们时抛出.
请尝试以下方法:
int y = 259;
byte x = checked((byte)y);
Run Code Online (Sandbox Code Playgroud)
你会看到它抛出一个OverflowException
.
unchecked
模式中的行为是截断而不是钳位的原因主要是出于性能原因,每次未经检查的强制转换都需要条件逻辑来在大多数时间不需要时将值钳位并且可以手动完成.
另一个原因是钳位会导致数据丢失,这可能是不可取的.我不宽恕以下代码,但看过它(见这个答案):
int input = 259;
var firstByte = (byte)input;
var secondByte = (byte)(input >> 8);
int reconstructed = (int)firstByte + (secondByte << 8);
Assert.AreEqual(reconstructed, input);
Run Code Online (Sandbox Code Playgroud)
如果firstByte
作为3以外的任何东西出来,这根本不起作用.
我最常依赖数字结转的地方之一是在实现时GetHashCode()
,请参阅这个答案,什么是由Jon Skeet 覆盖的System.Object.GetHashCode的最佳算法.GetHashCode
如果溢出意味着我们受到限制,实施体面将是一场噩梦Int32.MaxValue
.
归档时间: |
|
查看次数: |
179 次 |
最近记录: |