C# 使用来自 "Bits" 的二进制运算构建整数值
C# Building a Integer value with Binary operations from "Bits"
我有一个字节数组,实际上是这样的二进制值
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
二进制表示为1111 1110
(0xFF
= 0
, 0xF0
= 1
).
需要由此构建的整数或字节的值为0xFE
(254)。
我考虑过将 buf
转换为 1
和 0
的字符串,然后再转换回整数,但必须存在更优雅的方法来完成此操作二元运算。
已知可以完美执行此操作的 Pascal 代码是(使用字符串):
if NumberOfBytes > 0 then begin // there was a response
for c := Length(Str) downto 1 do begin
Ch := Str[c];
if (ord(ch) AND 2) = 0 then begin
Sin := Sin + '0';
end else begin
Sin := Sin + '1';
end;
INC(Teller);
if (Teller mod 8) = 0 then begin
N := BinaryStrToByte(Sin);
Edit2.Text := Edit2.Text + ByteHex(N) + ' ' ;
Sin := '';
end;
end;
还有 C 代码,由于行为上的一些差异,似乎无法移植到 C#:
for(bytes = 0; bytes < len; bytes++)
{
newByte=0;
for(bits=0; bits<8; bits++)
{
newByte >>= 1;
if(inBuf[0]==0xff)
{
newByte |= 0x80;
}
}
pBuf[bytes]=newByte;
}
我想有效地遍历我的原始数组,然后将一个真正的二进制 0
或 1
放入 int
或 byte
,这取决于我是否有当前位置的 0xF0
或 0xFF
值。
这可能会成功:
public static void Main()
{
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
byte result = 0;
foreach(var b in buf.Reverse())
{
result <<= 1;
if(b == 0xFF) result |= 1;
}
Console.WriteLine(result);
}
具有最少分支(和 LINQ 调用)的方法:
byte result = 0x00;
foreach(byte b in buf) {
result >>= 0x01;
byte bs = b;
bs <<= 0x07;
result |= bs;
}
此代码假设每个字节的最低有效位确定 0
(在 0xf0=1111 0000
的情况下)是 1
(在 0xff=1111 1111
的情况下) ) 应添加。
Mono C# Interactive 中的演示 shell:
csharp> byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
csharp> byte result = 0x00;
csharp> foreach(byte b in buf) {
> result >>= 0x01;
> byte bs = b;
> bs <<= 0x07;
> result |= bs;
> }
csharp> result.ToString("X");
"FE"
这里有一些更通用的类似 LINQ 的解决方案:
将字节转换为位的方法(在本例中表示为布尔值)
public static IEnumerable<Boolean> BytesToBooleans(IEnumerable<Byte> bytes)
{
if (bytes == null)
throw new ArgumentNullException("bytes");
return bytes
.Select(b =>
{
if (b == 0xF0)
return false;
if (b == 0xFF)
return true;
throw new ArgumentException();
});
}
将布尔值解释为从最低位开始的位的方法:
public static IEnumerable<Byte> BooleansAsBitsFromLowest(this IEnumerable<Boolean> bits)
{
if (bits == null)
throw new ArgumentNullException("bits");
Int32 bitsInByte = 0;
Byte curByte = 0;
foreach (var bit in bits)
{
var mask = (Byte)(bit ?
0x1 : 0x0);
mask = (Byte)(mask << bitsInByte);
curByte |= mask;
bitsInByte++;
if (bitsInByte == 8)
{
yield return curByte;
curByte = 0;
bitsInByte = 0;
}
}
if (bitsInByte != 0)
yield return curByte;
}
这是用法:
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
var bytesFromBits = BytesToBooleans(buf)
.BooleansAsBitsFromLowest();
foreach (var resultingByte in bytesFromBits)
{
Console.WriteLine(resultingByte.ToString("X2"));
}
我有一个字节数组,实际上是这样的二进制值
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
二进制表示为1111 1110
(0xFF
= 0
, 0xF0
= 1
).
需要由此构建的整数或字节的值为0xFE
(254)。
我考虑过将 buf
转换为 1
和 0
的字符串,然后再转换回整数,但必须存在更优雅的方法来完成此操作二元运算。
已知可以完美执行此操作的 Pascal 代码是(使用字符串):
if NumberOfBytes > 0 then begin // there was a response
for c := Length(Str) downto 1 do begin
Ch := Str[c];
if (ord(ch) AND 2) = 0 then begin
Sin := Sin + '0';
end else begin
Sin := Sin + '1';
end;
INC(Teller);
if (Teller mod 8) = 0 then begin
N := BinaryStrToByte(Sin);
Edit2.Text := Edit2.Text + ByteHex(N) + ' ' ;
Sin := '';
end;
end;
还有 C 代码,由于行为上的一些差异,似乎无法移植到 C#:
for(bytes = 0; bytes < len; bytes++)
{
newByte=0;
for(bits=0; bits<8; bits++)
{
newByte >>= 1;
if(inBuf[0]==0xff)
{
newByte |= 0x80;
}
}
pBuf[bytes]=newByte;
}
我想有效地遍历我的原始数组,然后将一个真正的二进制 0
或 1
放入 int
或 byte
,这取决于我是否有当前位置的 0xF0
或 0xFF
值。
这可能会成功:
public static void Main()
{
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
byte result = 0;
foreach(var b in buf.Reverse())
{
result <<= 1;
if(b == 0xFF) result |= 1;
}
Console.WriteLine(result);
}
具有最少分支(和 LINQ 调用)的方法:
byte result = 0x00;
foreach(byte b in buf) {
result >>= 0x01;
byte bs = b;
bs <<= 0x07;
result |= bs;
}
此代码假设每个字节的最低有效位确定 0
(在 0xf0=1111 0000
的情况下)是 1
(在 0xff=1111 1111
的情况下) ) 应添加。
Mono C# Interactive 中的演示 shell:
csharp> byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
csharp> byte result = 0x00;
csharp> foreach(byte b in buf) {
> result >>= 0x01;
> byte bs = b;
> bs <<= 0x07;
> result |= bs;
> }
csharp> result.ToString("X");
"FE"
这里有一些更通用的类似 LINQ 的解决方案:
将字节转换为位的方法(在本例中表示为布尔值)
public static IEnumerable<Boolean> BytesToBooleans(IEnumerable<Byte> bytes)
{
if (bytes == null)
throw new ArgumentNullException("bytes");
return bytes
.Select(b =>
{
if (b == 0xF0)
return false;
if (b == 0xFF)
return true;
throw new ArgumentException();
});
}
将布尔值解释为从最低位开始的位的方法:
public static IEnumerable<Byte> BooleansAsBitsFromLowest(this IEnumerable<Boolean> bits)
{
if (bits == null)
throw new ArgumentNullException("bits");
Int32 bitsInByte = 0;
Byte curByte = 0;
foreach (var bit in bits)
{
var mask = (Byte)(bit ?
0x1 : 0x0);
mask = (Byte)(mask << bitsInByte);
curByte |= mask;
bitsInByte++;
if (bitsInByte == 8)
{
yield return curByte;
curByte = 0;
bitsInByte = 0;
}
}
if (bitsInByte != 0)
yield return curByte;
}
这是用法:
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
var bytesFromBits = BytesToBooleans(buf)
.BooleansAsBitsFromLowest();
foreach (var resultingByte in bytesFromBits)
{
Console.WriteLine(resultingByte.ToString("X2"));
}