我正在编写一个数字转换器。如何在C#中将整数转换为二进制字符串,而不使用内置函数(Convert.ToString
根据给定的值执行不同的操作)?
- 二进制 -> 符号大小
- 二进制 -> 反码
- 二进制 -> 补码
我正在编写一个数字转换器。如何在C#中将整数转换为二进制字符串,而不使用内置函数(Convert.ToString
根据给定的值执行不同的操作)?
简单的解决方案:
IntToBinValue = Convert.ToString(6, 2);
今天几乎所有的计算机都使用二进制补码(two's complement)表示法,因此如果您进行直接转换,您将得到这个数的二进制补码字符串:
public string Convert(int x) {
char[] bits = new char[32];
int i = 0;
while (x != 0) {
bits[i++] = (x & 1) == 1 ? '1' : '0';
x >>= 1;
}
Array.Reverse(bits, 0, i);
return new string(bits);
}
这是你进行剩余两种转换的基础。对于符号-大小(sign-magnitude)表示法,只需要提前提取符号并转换其绝对值:
byte sign;
if (x < 0) {
sign = '1';
x = -x;
} else {
sign = '0';
}
string magnitude = Convert(x);
对于一的补数,在数字为负时减去1:
if (x < 0)
x--;
string onec = Convert(x);
decimal.GetBits(someValue)
将十进制转换为二进制表示形式。BitConverter.GetBytes
对从decimal.GetBits()
返回的元素进行转换,将整数转换为字节。decimal.GetBits()
文档很有用。BitConverter
包含用于将数字转换为字节的方法,这对于获取二进制表示形式很方便。 GetBytes()
和ToInt32()
方法对于每个方向的转换都很方便。如果您觉得更容易解释为1和0的十六进制字符串,则ToString()
重载很方便。decimal
类型。 - kbrimington var a = Convert.ToString(4, 2).PadLeft(8, '0');
从.NET 8开始,二进制格式说明符(B)(终于)被引入,使得任何额外的转换功能(内置或自定义)都变得过时了(除非你想做一些非常特定的事情,比如在每个字节或半字节之间添加下划线)。现在,它只是默认的整数数值类型的ToString()
方法的标准数值格式字符串的一部分:
int i = 42;
string binary = i.ToString("B"); // 101010
int j = 0x0f0f;
// you can specify the number of digits in the result string, for example 16:
string itsSoSimpleNow = $"{j:B16}"; // 0000111100001111
// this was not possible with Convert.ToString(...) before
ulong k = ulong.MaxValue;
string evenUlongsWorkFinally = k.ToString("B"); // 11...11
B
或 b
作为说明符,它们没有区别 :)
如果你现在被困在旧版的.NET中(或者真的想自定义)
到目前为止,我还没有看到一个简单的基于ASCII的解决方案,所以这里有一个:public static string ToBinaryString(ulong u)
{
Span<byte> ascii = stackalloc byte[64];
for (int i = 0; i < 64; i++)
{
// we want the MSB to be on the left, so we need to reverse everything
// other than that we simply grab the ith bit (from the LSB)
// and simply OR that to the ASCII character '0' (0x30).
// if the bit was 0 the result is '0' itself, otherwise
// if the bit was 1 then the result is '0' | 1 (0x30 | 1) which
// yields 0x31 which is also conveniently the ASCII code for '1'.
ascii[63 - i] = (byte)((u & (1uL << i)) >> i | '0');
}
return Encoding.ASCII.GetString(ascii);
}
public static string ToBinaryString(int value)
{
// note the cast to unsigned here.
// we don't want any funny negative values in here.
// the result will be the two's complement binary representation of negative values
uint u = (uint)value;
Span<byte> ascii = stackalloc byte[32];
for (int i = 0; i < 32; i++)
{
ascii[31 - i] = (byte)((u & (1u << i)) >> i | '0');
}
return Encoding.ASCII.GetString(ascii);
}
string binaryString = "011100100111001001110011";
int G = 0;
for (int i = 0; i < binaryString.Length; i++)
G += (int)((binaryString[binaryString.Length - (i + 1)] & 1) << (i % 32));
Console.WriteLine(G); //7500403
binaryString = string.Empty;
for (int i = 31; i >= 0; i--)
{
binaryString += (char)(((G & (1 << (i % 32))) >> (i % 32)) | 48);
}
Console.WriteLine(binaryString); //00000000011100100111001001110011
(uint)G & (1
而不是G & (1
。修复后代码如下:binaryString += (char)((((uint)G & (1 << (i % 32))) >> (i % 32)) | 48);
即可解决问题。如果不进行修复,在处理正数时仍然可以正常工作。 - user12515980这里有一个优雅的解决方案:
// Convert Integer to binary and return as string
private static string GetBinaryString(Int32 n)
{
char[] b = new char[sizeof(Int32) * 8];
for (int i = 0; i < b.Length; i++)
b[b.Length-1 - i] = ((n & (1 << i)) != 0) ? '1' : '0';
return new string(b).TrimStart('0');
}
您可以从头开始逐位构建数字表示。
不确定您不想使用哪些内置函数,但是您可以逐个字符构建字符串吗?
对于补码和反码,需要进行额外的计算步骤。
或者这对您的需求来说太基础了吗?
这是一个不安全的实现:
private static unsafe byte[] GetDecimalBytes(decimal d)
{
byte* dp = (byte*) &d;
byte[] result = new byte[sizeof(decimal)];
for (int i = 0; i < sizeof(decimal); i++, dp++)
{
result[i] = *dp;
}
return result;
}
这里是回滚操作:
private static unsafe decimal GetDecimal(Byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException("bytes");
if (bytes.Length != sizeof(decimal))
throw new ArgumentOutOfRangeException("bytes", "length must be 16");
decimal d = 0;
byte* dp = (byte*)&d;
byte[] result = new byte[sizeof(decimal)];
for (int i = 0; i < sizeof(decimal); i++, dp++)
{
*dp = bytes[i];
}
return d;
}