65.9K
CodeProject 正在变化。 阅读更多。
Home

二进制、八进制和十六进制 32 位结构体

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (16投票s)

2008年8月7日

CPOL

4分钟阅读

viewsIcon

51692

downloadIcon

604

简化了基数 2、8 和 16 位数据的用法。

Bin32.png

引言

虽然数据在内存或磁盘中显然以二进制形式存储,但 .NET 会在我们希望查看数据或设置值时自动将其转换为十进制(基数 10)。它确实提供了一些用于获取或设置其他基数的值的功能,如下所示。

内置函数

设置 Int32(基数 = 2 表示二进制,8 表示八进制,16 表示十六进制):Convert.ToInt32 (string, base)。例如:

string binaryString = "11111111";
int i = Convert.ToInt32 (binaryString, 2);

i 现在等于 255。

十六进制的替代方法

int i = 0xFF;
i 现在等于 255。

从 Int32 获取值Convert.ToString (integer, base)。例如:

int i = 255;
string binaryString = Convert.ToString (i, 2);

binaryString 现在等于 1111111。

此类库

这些在大多数情况下都足够了,但我经常发现我需要一种更自然/更灵活的方式来包装这些函数。此类库是一些简单的代码来解决这个问题。所有结构体都围绕一个 Int32 (m_Value) 构建,因此分别称为 Bin32Oct32Hex32

在每个结构体中,您首先会注意到几个 implicit 和一个 explicit 运算符方法。

Bin32 中,第一个是

public static implicit operator Bin32(int value) {... }

这段魔法允许我们直接接受一个 int 来创建 Bin32 的实例,而无需在我们的代码中调用重载构造函数(它会自动调用私有构造函数)。例如,您可以这样做:

Bin32 binaryValue = 255;

而不是通常的

Bin32 binaryValue = new Bin32(255);

下一个类似,但允许我们使用字符串

public static implicit operator Bin32(string value) {... }

因此,我们可以简单地使用

Bin32 binaryValue = "11111111";

再往下是一个与第一个类似的方法,但 Bin32int 的顺序颠倒了。

public static implicit operator int(Bin32 value) {... }

这使得我们可以自动将我们的值用作 int,而无需显式转换。

Bin32 binaryValue = "11111111";
int i = binaryValue;

下一行与前一行不同,因为它是一个 explicit 而不是 implicit

public static explicit operator string(Bin32 value) {... }

通过使用 explicit 关键字,这意味着我们必须显式转换为此类型才能使用该方法。

Bin32 binaryValue = "11111111";
string binaryString = (string)binaryValue;

为什么不在这里使用 implicit?嗯,拥有多个隐式返回类型可能会导致一些严重的头疼。只需尝试将 explicit 改为 implicit,然后尝试

Console.WriteLine(binaryValue);

糟糕!这会产生很多歧义,因为它不知道要写入控制台的内容 - **选择太多了!**

最初,我将 string 设置为 implicit,将 int 设置为 explicit。这样可以正常工作,但需要更多的代码,因为所有一元、二元、逻辑和条件运算符都需要重载。将 int 保持为 implicit,我们可以使用 Microsoft 已经为 Int32 运算符完成的代码 :-)。

有关运算符重载的更多信息,请参阅我的文章:C# 运算符重载入门

除了显式转换外,还有两个 ToString 方法(一个用于 Oct32)。

我实现了标准的 IComparableIEquatable 接口。ParseToStringTryParse 方法主要包含在本文开头介绍的内置函数中。

这里还有一个类 - 一个名为 ExtensionMethods 的静态类,其中声明了一些简单的扩展方法,为 intstring 提供了额外的功能,而无需我们实际调用任何 Bin32Oct32Hex32 实例。

使用中

BinOctHex.dll 的引用添加到您的项目中。使用这些结构体非常简单。附带了一个简单的示例。您对 int 可以做的所有常规操作都可以对这些结构体中的任何一个进行(包括位移,这在十六进制和二进制中更有意义)。您还可以对这些结构体的组合执行操作。例如:

(bin number % hexnumber) / octnumber;

使用动机

我经常需要对多个二进制和十六进制数字进行计算,并将结果以任一基数显示(八进制较少,但我为完整性包含了它)。

想象一下像这样的简单计算:

((1 + 2 + 3 + 4 + 5) % 4) * 15 = ?

如果它们都是 int,那很容易,但如果它们是混合的二进制和十六进制字符串呢?

((00000001 + 00000010 + 00000011 + 00000100 + 00000101) % 00000100) * 0F = ?(base 8)

目前,您必须手动将每个字符串转换为 int,然后再次转换以显示正确基数下的答案。使用这个,您可以像看到的那样执行计算。

string a1 = "00000001";
string b1 = "00000010";
string c1 = "00000011";
string d1 = "00000100";
string e1 = "00000101";
string f1 = "00000100";
string g1 = "0F";

// Using methods built in.
int h1 = (
    (Convert.ToInt32(a1, 2) +
    Convert.ToInt32(b1, 2) +
    Convert.ToInt32(c1, 2) +
    Convert.ToInt32(d1, 2) +
    Convert.ToInt32(e1, 2))
    % Convert.ToInt32(f1, 2))
    * Convert.ToInt32(g1, 16);
Console.WriteLine(Convert.ToString(h1, 8));

Bin32 a2 = a1;
Bin32 b2 = b1;
Bin32 c2 = c1;
Bin32 d2 = d1;
Bin32 e2 = e1;
Bin32 f2 = f1;
Hex32 g2 = g1;

// Using Bin32, Oct32, Hex32 structs - a simple one liner
Oct32 h2 = ((a2 + b2 + c2 + d2 + e2) % f2) * g2;
Console.WriteLine((String)h2);

我还对上面的代码进行了计时,两者都以大致相同的时间执行 - 有时第一部分稍快一些,有时第二部分 - 所以它根本不会减慢速度。直接使用 int 的速度大约是快 50 倍,但如果您的数据是其他基数,那么您总是需要进行转换。如果您想将其更改为 int 来消除开销 - 这就是隐式转换的用途。

历史

© . All rights reserved.