鉴于以下代码将byte
个值uint
打包为private static void Pack(byte x, byte y, byte z, byte w)
{
this.PackedValue = (uint)x |
((uint)y << 8) |
((uint)z << 16) |
((uint)w << 24);
}
。
*, +, / and -
是否可以将值byte
等数学运算符应用于可以将其解压缩到正确的uint result = this.PackedValue * other.PackedValue
等效值的方式?
EDIT。
澄清一下,如果我试图将该值乘以另一个打包值
public byte[] ToBytes()
{
return new[]
{
(byte)(this.PackedValue & 0xFF),
(byte)((this.PackedValue >> 8) & 0xFF),
(byte)((this.PackedValue >> 16) & 0xFF),
(byte)((this.PackedValue >> 24) & 0xFF)
};
}
然后使用以下内容解压缩...
void Main()
{
uint x = PackUint(128, 128, 128, 128);
uint y = (uint)(x * 1.5f);
byte[] b1 = ToBytes(x);
x.Dump(); // 2155905152
b1.Dump(); // 128, 255, 128, 255 RIGHT!
byte[] b2 = ToBytes(y);
b2.Dump(); // 0, 192, 192, 192 WRONG! Should be 192, 192, 192, 192
}
// Define other methods and classes here
private static uint PackUint(byte x, byte y, byte z, byte w)
{
return ((uint)x) |
((uint)y << 8) |
((uint)z << 16) |
((uint)w << 24);
}
public static byte[] ToBytes(uint packed)
{
return new[]
{
(byte)(packed & 0xFF),
(byte)((packed >> 8) & 0xFF),
(byte)((packed >> 16) & 0xFF),
(byte)((packed >> 24) & 0xFF)
};
}
我得到了错误的结果。
这是一个完整的代码示例,显示了预期和实际结果。
ISNUMERIC
答案 0 :(得分:5)
它不适用于1.5f
的唯一原因是因为浮点数不够精确。试试1.5d
(对于double
),您的示例将有效。然而,这种方法仅限于&#34; nice&#34;情况,即保证每个字节的结果是整数的情况。一个特例是当你乘以一个整数时,只要四个结果都没有溢出,它就会一直有效。
如果没有单个字节溢出,也可以对加法和减法执行此操作。显然任何溢出都会弄乱附近的字节。如果您希望对负字节(-128 ... 127)使用2的补码,则这尤其成问题,因为将3添加到-2也是&#34;溢出&#34;并且会弄乱下一个字节。
答案 1 :(得分:0)
更好的解决方案是使用Blitting。
void Main()
{
Byte X = 0x13;
Byte Y = 0x6A;
Byte Z = 0xA3;
Byte W = 0x94;
Foo foo = new Foo(X, Y, Z, W);
uint i = foo ;
Foo bar = (uint)(i * 1.5d);
Console.WriteLine(X * 1.5d == bar.X);
Console.WriteLine(Y * 1.5d == bar.Y);
Console.WriteLine(Z * 1.5d == bar.Z);
Console.WriteLine(W * 1.5d == bar.W);
}
[StructLayout(LayoutKind.Explicit)]
public struct Foo
{
[FieldOffset(0)]
public byte X;
[FieldOffset(1)]
public byte Y;
[FieldOffset(2)]
public byte Z;
[FieldOffset(3)]
public byte W;
[FieldOffset(0)]
public uint Value;
public Foo(byte x, byte y, byte z, byte w) : this()
{
X = x;
Y = y;
Z = z;
W = w;
}
public static implicit operator Foo(uint value)
{
return new Foo(){ Value = value };
}
public static implicit operator uint(Foo foo)
{
return foo.Value;
}
}
我们创建了一个新类型,它不是通过位移,而是直接(类型安全)访问uint
内的内存地址。