In Java, I could do
在Java中,我可以做到。
BigInteger b = new BigInteger(500);
Then format it as I pleased
然后按照我的意愿格式化。
b.toString(2); //binary
b.toString(8); //octal
b.toString(10); //decimal
b.toString(16); //hexadecimal
In C#, I can do
在c#中,我可以做到。
int num = int.Parse(b.ToString());
Convert.ToString(num,2) //binary
Convert.ToString(num,8) //octal
etc. But I can only do it with long
values and smaller. Is there some method to print a BigInteger with a specified base? I posted this, BigInteger Parse Octal String?, yesterday and received the solution of how to convert basically all strings to BigInteger values, but haven't had success outputting.
等等,但我只能用更长的值和更小的值来做。是否有一些方法可以打印具有指定基数的BigInteger ?我发布了这个,BigInteger Parse Octal字符串?昨天,我们得到了如何将所有字符串转换为BigInteger值的解决方案,但是没有成功输出。
3 个解决方案
#1
25
Convert BigInteger
to decimal, hex, binary, octal string:
Let's start with a BigInteger
value:
让我们从一个BigInteger值开始:
BigInteger bigint = BigInteger.Parse("123456789012345678901234567890");
Base 10 and Base 16
The built-in Base 10 (decimal) and base 16 (hexadecimal) coversions are easy:
内置的基数10(十进制)和基数16(十六进制)的共版很简单:
// Convert to base 10 (decimal):
string base10 = bigint.ToString();
// Convert to base 16 (hexadecimal):
string base16 = bigint.ToString("X");
Leading Zeros (positive vs. negative BigInteger values)
Take note, that ToString("X")
ensures hexadecimal strings have a leading zero when the value of BigInteger
is positive. This is unlike the usual behavior of ToString("X")
when converting from other value types where leading zeros are suppressed.
注意,ToString(“X”)确保在BigInteger的值为正数时,十六进制字符串的前导为零。这不同于ToString(“X”)的通常行为,当从其他值类型转换为被抑制的前导零值时。
EXAMPLE:
例子:
var positiveBigInt = new BigInteger(128);
var negativeBigInt = new BigInteger(-128);
Console.WriteLine(positiveBigInt.ToString("X"));
Console.WriteLine(negativeBigInt.ToString("X"));
RESULT:
结果:
080
80
There is a purpose for this behavior as a leading zero indicates the BigInteger
is a positive value--essentially, the leading zero provides the sign. This is necessary (as opposed to other value type conversions) because a BigInteger
has no fixed size; therefore, there is no designated sign bit. The leading zero identifies a positive value, as opposed to a negative one. This allows for "round-tripping" BigInteger
values out through ToString()
and back in through Parse()
. This behavior is discussed on the BigInteger Structure page on MSDN.
这个行为的目的是作为一个前导零,表示BigInteger是一个正数——本质上,前导零提供了这个符号。这是必要的(与其他值类型转换相反),因为BigInteger没有固定大小;因此,没有指定的符号位。前导零表示一个正值,而不是一个负值。这允许通过ToString()返回“往返”BigInteger值,并通过Parse()返回。此行为在MSDN上的BigInteger结构页面上进行了讨论。
Extension methods: BigInteger to Binary, Hex, and Octal
Here is a class containing extension methods to convert BigInteger
instances to binary, hexadecimal, and octal strings:
这里是一个类,其中包含将BigInteger实例转换为二进制、十六进制和八进制字符串的扩展方法:
using System;
using System.Numerics;
using System.Text;
/// <summary>
/// Extension methods to convert <see cref="System.Numerics.BigInteger"/>
/// instances to hexadecimal, octal, and binary strings.
/// </summary>
public static class BigIntegerExtensions
{
/// <summary>
/// Converts a <see cref="BigInteger"/> to a binary string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing a binary
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToBinaryString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base2 = new StringBuilder(bytes.Length * 8);
// Convert first byte to binary.
var binary = Convert.ToString(bytes[idx], 2);
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
// Append binary string to StringBuilder.
base2.Append(binary);
// Convert remaining bytes adding leading zeros.
for (idx--; idx >= 0; idx--)
{
base2.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
}
return base2.ToString();
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a hexadecimal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing a hexadecimal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToHexadecimalString(this BigInteger bigint)
{
return bigint.ToString("X");
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a octal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing an octal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToOctalString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base8 = new StringBuilder(((bytes.Length / 3) + 1) * 8);
// Calculate how many bytes are extra when byte array is split
// into three-byte (24-bit) chunks.
var extra = bytes.Length % 3;
// If no bytes are extra, use three bytes for first chunk.
if (extra == 0)
{
extra = 3;
}
// Convert first chunk (24-bits) to integer value.
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
// Convert 24-bit integer to octal without adding leading zeros.
var octal = Convert.ToString(int24, 8);
// Ensure leading zero exists if value is positive.
if (octal[0] != '0' && bigint.Sign == 1)
{
base8.Append('0');
}
// Append first converted chunk to StringBuilder.
base8.Append(octal);
// Convert remaining 24-bit chunks, adding leading zeros.
for (; idx >= 0; idx -= 3)
{
int24 = (bytes[idx] << 16) + (bytes[idx - 1] << 8) + bytes[idx - 2];
base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0'));
}
return base8.ToString();
}
}
On first glance, these methods may seem more complex than necessary. A bit of extra complexity is, indeed, added to ensure the proper leading zeros are present in the converted strings.
乍一看,这些方法似乎更复杂。确实,添加了一些额外的复杂性,以确保在转换后的字符串中存在适当的前导零。
Let's examine each extension method to see how they work:
让我们检查每个扩展方法,看看它们是如何工作的:
BigInteger.ToBinaryString()
Here is how to use this extension method to convert a BigInteger
to a binary string:
下面是如何使用此扩展方法将BigInteger转换为二进制字符串:
// Convert BigInteger to binary string.
bigint.ToBinaryString();
The fundamental core of each of these extension methods is the BigInteger.ToByteArray()
method. This method converts a BigInteger
to a byte array, which is how we can get the binary representation of a BigInteger
value:
每个扩展方法的基本核心是BigInteger.ToByteArray()方法。该方法将一个BigInteger转换为一个字节数组,这就是我们如何得到一个BigInteger值的二进制表示:
var bytes = bigint.ToByteArray();
Beware, though, the returned byte array is in little-endian order, so the first array element is the least-significant byte (LSB) of the BigInteger
. Since a StringBuilder
is used to build the output string--which starts at the most-significant digit (MSB)--the byte array must be iterated in reverse so that the most-significant byte is converted first.
但是要注意,返回的字节数组在little-endian顺序中,所以第一个数组元素是BigInteger的最小有效字节(LSB)。由于StringBuilder用于构建输出字符串——从最重要的数字(MSB)开始——字节数组必须进行反向迭代,以使最重要的字节首先转换。
Thus, an index pointer is set to the most significant digit (the last element) in the byte array:
因此,将索引指针设置为字节数组中最重要的数字(最后一个元素):
var idx = bytes.Length - 1;
To capture the converted bytes, a StringBuilder
is created:
要捕获转换后的字节,需要创建一个StringBuilder:
var base2 = new StringBuilder(bytes.Length * 8);
The StringBuilder
constructor takes the capacity for the StringBuilder
. The capacity needed for the StringBuilder
is calculated by taking the number of bytes to convert multiplied by eight (eight binary digits result from each byte converted).
StringBuilder构造函数接受StringBuilder的容量。StringBuilder所需的容量是通过将字节数乘以8(每个字节转换成8个二进制数字的结果)来计算的。
The first byte is then converted to a binary string:
然后将第一个字节转换为二进制字符串:
var binary = Convert.ToString(bytes[idx], 2);
At this point, it is necessary to ensure that a leading zero exists if the BigInteger
is a positive value (see discussion above). If the first converted digit is not a zero, and bigint
is positive, then a '0'
is appended to the StringBuilder
:
在这一点上,有必要确保如果BigInteger是一个正值(参见上面的讨论),则存在一个前导零。如果第一个转换的数字不是0,而bigint是正的,那么一个“0”被附加到StringBuilder:
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
Next, the converted byte is appended to the StringBuilder
:
接下来,将转换后的字节附加到StringBuilder:
base2.Append(binary);
To convert the remaining bytes, a loop iterates the remainder of the byte array in reverse order:
为了转换剩余的字节,一个循环以相反的顺序遍历字节数组的其余部分:
for (idx--; idx >= 0; idx--)
{
base16.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
}
Notice that each converted byte is padded on the left with zeros ('0'), as necessary, so that the converted string is eight binary characters. This is extremely important. Without this padding, the hexadecimal value '101' would be converted to a binary value of '11'. The leading zeros ensure the conversion is '100000001'.
注意,每个转换后的字节都是用0('0')来填充的,因此转换后的字符串是8个二进制字符。这是非常重要的。如果没有这个填充,十六进制值“101”将转换为“11”的二进制值。前导零保证转换为“100000001”。
When all bytes are converted, the StringBuilder
contains the complete binary string, which is returned by the extension method:
当所有字节都被转换时,StringBuilder包含完整的二进制字符串,该字符串由扩展方法返回:
return base2.ToString();
BigInteger.ToOctalString
Converting a BigInteger
to an octal (base 8) string is more complicated. The problem is octal digits represent three bits which is not an even multiple of the eight bits held in each element of the byte array created by BigInteger.ToByteArray()
. To solve this problem, three bytes from the array are combined into chunks of 24-bits. Each 24-bit chunk evenly converts to eight octal characters.
将BigInteger转换为八进制(基数8)字符串更复杂。问题是八进制数字表示三比特,它不是由BigInteger.ToByteArray()所创建的字节数组的每个元素中包含的8位元的偶数倍。为了解决这个问题,将数组中的三个字节合并成24位的块。每个24位块平均转换为8个八进制字符。
The first 24-bit chunk requires some modulo math:
第一个24位块需要一些模块数学:
var extra = bytes.Length % 3;
This calculation determines how many bytes are "extra" when the entire byte array is split into three-byte (24-bit) chunks. The first conversion to octal (the most-significant digits) gets the "extra" bytes so that all remaining conversions will get three bytes each.
这个计算决定了在将整个字节数组分成三个字节(24位)块时,“额外”的字节数。第一个转换到八进制(最有效的数字)得到“额外的”字节,这样所有剩余的转换将得到三个字节。
If there are no "extra" bytes, then the first chunk gets a full three bytes:
如果没有“额外”字节,那么第一个块将得到一个完整的三个字节:
if (extra == 0)
{
extra = 3;
}
The first chunk is loaded into an integer variable called int24
that holds up to 24-bits. Each byte of the chunk is loaded. As additional bytes are loaded, the previous bits in int24
are left-shifted by 8-bits to make room:
第一个块被加载到一个名为int24的整数变量中,该变量可以容纳24位元。块的每个字节都被加载。由于加载了额外的字节,int24中的前位是由8位左移的,以腾出空间:
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
Conversion of a 24-bit chunk to octal is accomplished by:
将24位块转换为八进制的方法是:
var octal = Convert.ToString(int24, 8);
Again, the first digit must be a leading zero if the BigInteger
is a positive value:
同样,如果BigInteger是一个正数,那么第一个数字必须是一个前导零:
// Ensure leading zero exists if value is positive.
if (octal[0] != '0' && bigint.Sign == 1)
{
base8.Append('0');
}
The first converted chunk is appended to the StringBuilder
:
第一个转换的块被附加到StringBuilder:
base8.Append(octal);
The remaining 24-bit chunks are converted in a loop:
剩下的24位块被转换成一个循环:
for (; idx >= 0; idx -= 3)
{
int24 = (bytes[idx] << 16) + (bytes[idx -1] << 8) + bytes[idx - 2];
base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0'));
}
Like the binary conversion, each converted octal string is left-padded with zeros so that '7' becomes '00000007'. This ensures that zeros won't be dropped from the middle of converted strings (i.e., '17' instead of '100000007').
就像二进制转换一样,每个转换的八进制字符串都是左加零的,所以“7”变成“00000007”。这将确保不会从转换后的字符串中删除0。,“17”而不是“100000007”。
Conversion to Base x?
Converting a BigInteger
to other number bases could be far more complicated. As long as the number base is a power of two (i.e., 2, 4, 8, 16) the byte array created by BigInteger.ToByteArray()
can be appropriately split into chunks of bits and converted.
将一个大整数转换为其他数基可能要复杂得多。只要基数是2的幂(即。由BigInteger.ToByteArray()创建的字节数组可以适当地分割成块并转换。
However, if the number base is not a power of two, the problem becomes much more complicated and requires a good deal of looping and division. As such number base conversions are rare, I have only covered the popular computing number bases here.
但是,如果基数不是2的幂,问题就变得复杂得多,需要大量的循环和分割。由于这样的基数转换很少见,所以我只介绍了这里的流行计算基数。
#2
1
After a good long day of working with BigInteger, I got a better way of doing things to output the string in binary, try this! (works for negative numbers)
在与BigInteger一起工作了一整天之后,我找到了一种更好的方法来用二进制来输出字符串,试试这个!(适用于负数)
// Important note: when parsing hexadecimal string, make sure to prefix
// with 0 if the number is positive. Ex: 0F instead of F, and 01A3 instead of 1A3.
// If the number is negative, then the first bit should be set to 1.
var x = BigInteger.Parse("0F", NumberStyles.HexNumber); // Or: BigInteger.Parse("15")
var biBytes = x.ToByteArray();
var bits = new bool [8 * biBytes.Length];
new BitArray(x.ToByteArray()).CopyTo(bits, 0);
bits = bits.Reverse().ToArray(); // BigInteger uses little endian when extracting bytes (thus bits), so we inverse them.
var builder = new StringBuilder();
foreach(var bit in bits)
{
builder.Append(bit ? '1' : '0');
}
string final = Regex.Replace(builder.ToString(), @"^0+", ""); // Because bytes consume full 8 bits, we might occasionally get leading zeros.
Console.WriteLine(final);
Output: 1111
输出:1111
#3
0
This is a simple method to convert a BigInteger
to any base:
这是一个将BigInteger转换为任何基础的简单方法:
public static string ToNBase(BigInteger a, int n)
{
StringBuilder sb = new StringBuilder();
while (a > 0)
{
sb.Insert(0,a % n);
a /= n;
}
return sb.ToString();
}
It works perfectly for base 2-10. If you want it to produce hexadecimal or other higher base strings, You have to modify a % b
's form according to the base before inserting it.
以2-10为底,效果很好。如果您希望它产生十六进制或其他更高的基本字符串,您必须根据基础修改% b的格式,然后插入它。
#1
25
Convert BigInteger
to decimal, hex, binary, octal string:
Let's start with a BigInteger
value:
让我们从一个BigInteger值开始:
BigInteger bigint = BigInteger.Parse("123456789012345678901234567890");
Base 10 and Base 16
The built-in Base 10 (decimal) and base 16 (hexadecimal) coversions are easy:
内置的基数10(十进制)和基数16(十六进制)的共版很简单:
// Convert to base 10 (decimal):
string base10 = bigint.ToString();
// Convert to base 16 (hexadecimal):
string base16 = bigint.ToString("X");
Leading Zeros (positive vs. negative BigInteger values)
Take note, that ToString("X")
ensures hexadecimal strings have a leading zero when the value of BigInteger
is positive. This is unlike the usual behavior of ToString("X")
when converting from other value types where leading zeros are suppressed.
注意,ToString(“X”)确保在BigInteger的值为正数时,十六进制字符串的前导为零。这不同于ToString(“X”)的通常行为,当从其他值类型转换为被抑制的前导零值时。
EXAMPLE:
例子:
var positiveBigInt = new BigInteger(128);
var negativeBigInt = new BigInteger(-128);
Console.WriteLine(positiveBigInt.ToString("X"));
Console.WriteLine(negativeBigInt.ToString("X"));
RESULT:
结果:
080
80
There is a purpose for this behavior as a leading zero indicates the BigInteger
is a positive value--essentially, the leading zero provides the sign. This is necessary (as opposed to other value type conversions) because a BigInteger
has no fixed size; therefore, there is no designated sign bit. The leading zero identifies a positive value, as opposed to a negative one. This allows for "round-tripping" BigInteger
values out through ToString()
and back in through Parse()
. This behavior is discussed on the BigInteger Structure page on MSDN.
这个行为的目的是作为一个前导零,表示BigInteger是一个正数——本质上,前导零提供了这个符号。这是必要的(与其他值类型转换相反),因为BigInteger没有固定大小;因此,没有指定的符号位。前导零表示一个正值,而不是一个负值。这允许通过ToString()返回“往返”BigInteger值,并通过Parse()返回。此行为在MSDN上的BigInteger结构页面上进行了讨论。
Extension methods: BigInteger to Binary, Hex, and Octal
Here is a class containing extension methods to convert BigInteger
instances to binary, hexadecimal, and octal strings:
这里是一个类,其中包含将BigInteger实例转换为二进制、十六进制和八进制字符串的扩展方法:
using System;
using System.Numerics;
using System.Text;
/// <summary>
/// Extension methods to convert <see cref="System.Numerics.BigInteger"/>
/// instances to hexadecimal, octal, and binary strings.
/// </summary>
public static class BigIntegerExtensions
{
/// <summary>
/// Converts a <see cref="BigInteger"/> to a binary string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing a binary
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToBinaryString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base2 = new StringBuilder(bytes.Length * 8);
// Convert first byte to binary.
var binary = Convert.ToString(bytes[idx], 2);
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
// Append binary string to StringBuilder.
base2.Append(binary);
// Convert remaining bytes adding leading zeros.
for (idx--; idx >= 0; idx--)
{
base2.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
}
return base2.ToString();
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a hexadecimal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing a hexadecimal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToHexadecimalString(this BigInteger bigint)
{
return bigint.ToString("X");
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a octal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="System.String"/> containing an octal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToOctalString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base8 = new StringBuilder(((bytes.Length / 3) + 1) * 8);
// Calculate how many bytes are extra when byte array is split
// into three-byte (24-bit) chunks.
var extra = bytes.Length % 3;
// If no bytes are extra, use three bytes for first chunk.
if (extra == 0)
{
extra = 3;
}
// Convert first chunk (24-bits) to integer value.
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
// Convert 24-bit integer to octal without adding leading zeros.
var octal = Convert.ToString(int24, 8);
// Ensure leading zero exists if value is positive.
if (octal[0] != '0' && bigint.Sign == 1)
{
base8.Append('0');
}
// Append first converted chunk to StringBuilder.
base8.Append(octal);
// Convert remaining 24-bit chunks, adding leading zeros.
for (; idx >= 0; idx -= 3)
{
int24 = (bytes[idx] << 16) + (bytes[idx - 1] << 8) + bytes[idx - 2];
base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0'));
}
return base8.ToString();
}
}
On first glance, these methods may seem more complex than necessary. A bit of extra complexity is, indeed, added to ensure the proper leading zeros are present in the converted strings.
乍一看,这些方法似乎更复杂。确实,添加了一些额外的复杂性,以确保在转换后的字符串中存在适当的前导零。
Let's examine each extension method to see how they work:
让我们检查每个扩展方法,看看它们是如何工作的:
BigInteger.ToBinaryString()
Here is how to use this extension method to convert a BigInteger
to a binary string:
下面是如何使用此扩展方法将BigInteger转换为二进制字符串:
// Convert BigInteger to binary string.
bigint.ToBinaryString();
The fundamental core of each of these extension methods is the BigInteger.ToByteArray()
method. This method converts a BigInteger
to a byte array, which is how we can get the binary representation of a BigInteger
value:
每个扩展方法的基本核心是BigInteger.ToByteArray()方法。该方法将一个BigInteger转换为一个字节数组,这就是我们如何得到一个BigInteger值的二进制表示:
var bytes = bigint.ToByteArray();
Beware, though, the returned byte array is in little-endian order, so the first array element is the least-significant byte (LSB) of the BigInteger
. Since a StringBuilder
is used to build the output string--which starts at the most-significant digit (MSB)--the byte array must be iterated in reverse so that the most-significant byte is converted first.
但是要注意,返回的字节数组在little-endian顺序中,所以第一个数组元素是BigInteger的最小有效字节(LSB)。由于StringBuilder用于构建输出字符串——从最重要的数字(MSB)开始——字节数组必须进行反向迭代,以使最重要的字节首先转换。
Thus, an index pointer is set to the most significant digit (the last element) in the byte array:
因此,将索引指针设置为字节数组中最重要的数字(最后一个元素):
var idx = bytes.Length - 1;
To capture the converted bytes, a StringBuilder
is created:
要捕获转换后的字节,需要创建一个StringBuilder:
var base2 = new StringBuilder(bytes.Length * 8);
The StringBuilder
constructor takes the capacity for the StringBuilder
. The capacity needed for the StringBuilder
is calculated by taking the number of bytes to convert multiplied by eight (eight binary digits result from each byte converted).
StringBuilder构造函数接受StringBuilder的容量。StringBuilder所需的容量是通过将字节数乘以8(每个字节转换成8个二进制数字的结果)来计算的。
The first byte is then converted to a binary string:
然后将第一个字节转换为二进制字符串:
var binary = Convert.ToString(bytes[idx], 2);
At this point, it is necessary to ensure that a leading zero exists if the BigInteger
is a positive value (see discussion above). If the first converted digit is not a zero, and bigint
is positive, then a '0'
is appended to the StringBuilder
:
在这一点上,有必要确保如果BigInteger是一个正值(参见上面的讨论),则存在一个前导零。如果第一个转换的数字不是0,而bigint是正的,那么一个“0”被附加到StringBuilder:
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
Next, the converted byte is appended to the StringBuilder
:
接下来,将转换后的字节附加到StringBuilder:
base2.Append(binary);
To convert the remaining bytes, a loop iterates the remainder of the byte array in reverse order:
为了转换剩余的字节,一个循环以相反的顺序遍历字节数组的其余部分:
for (idx--; idx >= 0; idx--)
{
base16.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
}
Notice that each converted byte is padded on the left with zeros ('0'), as necessary, so that the converted string is eight binary characters. This is extremely important. Without this padding, the hexadecimal value '101' would be converted to a binary value of '11'. The leading zeros ensure the conversion is '100000001'.
注意,每个转换后的字节都是用0('0')来填充的,因此转换后的字符串是8个二进制字符。这是非常重要的。如果没有这个填充,十六进制值“101”将转换为“11”的二进制值。前导零保证转换为“100000001”。
When all bytes are converted, the StringBuilder
contains the complete binary string, which is returned by the extension method:
当所有字节都被转换时,StringBuilder包含完整的二进制字符串,该字符串由扩展方法返回:
return base2.ToString();
BigInteger.ToOctalString
Converting a BigInteger
to an octal (base 8) string is more complicated. The problem is octal digits represent three bits which is not an even multiple of the eight bits held in each element of the byte array created by BigInteger.ToByteArray()
. To solve this problem, three bytes from the array are combined into chunks of 24-bits. Each 24-bit chunk evenly converts to eight octal characters.
将BigInteger转换为八进制(基数8)字符串更复杂。问题是八进制数字表示三比特,它不是由BigInteger.ToByteArray()所创建的字节数组的每个元素中包含的8位元的偶数倍。为了解决这个问题,将数组中的三个字节合并成24位的块。每个24位块平均转换为8个八进制字符。
The first 24-bit chunk requires some modulo math:
第一个24位块需要一些模块数学:
var extra = bytes.Length % 3;
This calculation determines how many bytes are "extra" when the entire byte array is split into three-byte (24-bit) chunks. The first conversion to octal (the most-significant digits) gets the "extra" bytes so that all remaining conversions will get three bytes each.
这个计算决定了在将整个字节数组分成三个字节(24位)块时,“额外”的字节数。第一个转换到八进制(最有效的数字)得到“额外的”字节,这样所有剩余的转换将得到三个字节。
If there are no "extra" bytes, then the first chunk gets a full three bytes:
如果没有“额外”字节,那么第一个块将得到一个完整的三个字节:
if (extra == 0)
{
extra = 3;
}
The first chunk is loaded into an integer variable called int24
that holds up to 24-bits. Each byte of the chunk is loaded. As additional bytes are loaded, the previous bits in int24
are left-shifted by 8-bits to make room:
第一个块被加载到一个名为int24的整数变量中,该变量可以容纳24位元。块的每个字节都被加载。由于加载了额外的字节,int24中的前位是由8位左移的,以腾出空间:
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
Conversion of a 24-bit chunk to octal is accomplished by:
将24位块转换为八进制的方法是:
var octal = Convert.ToString(int24, 8);
Again, the first digit must be a leading zero if the BigInteger
is a positive value:
同样,如果BigInteger是一个正数,那么第一个数字必须是一个前导零:
// Ensure leading zero exists if value is positive.
if (octal[0] != '0' && bigint.Sign == 1)
{
base8.Append('0');
}
The first converted chunk is appended to the StringBuilder
:
第一个转换的块被附加到StringBuilder:
base8.Append(octal);
The remaining 24-bit chunks are converted in a loop:
剩下的24位块被转换成一个循环:
for (; idx >= 0; idx -= 3)
{
int24 = (bytes[idx] << 16) + (bytes[idx -1] << 8) + bytes[idx - 2];
base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0'));
}
Like the binary conversion, each converted octal string is left-padded with zeros so that '7' becomes '00000007'. This ensures that zeros won't be dropped from the middle of converted strings (i.e., '17' instead of '100000007').
就像二进制转换一样,每个转换的八进制字符串都是左加零的,所以“7”变成“00000007”。这将确保不会从转换后的字符串中删除0。,“17”而不是“100000007”。
Conversion to Base x?
Converting a BigInteger
to other number bases could be far more complicated. As long as the number base is a power of two (i.e., 2, 4, 8, 16) the byte array created by BigInteger.ToByteArray()
can be appropriately split into chunks of bits and converted.
将一个大整数转换为其他数基可能要复杂得多。只要基数是2的幂(即。由BigInteger.ToByteArray()创建的字节数组可以适当地分割成块并转换。
However, if the number base is not a power of two, the problem becomes much more complicated and requires a good deal of looping and division. As such number base conversions are rare, I have only covered the popular computing number bases here.
但是,如果基数不是2的幂,问题就变得复杂得多,需要大量的循环和分割。由于这样的基数转换很少见,所以我只介绍了这里的流行计算基数。
#2
1
After a good long day of working with BigInteger, I got a better way of doing things to output the string in binary, try this! (works for negative numbers)
在与BigInteger一起工作了一整天之后,我找到了一种更好的方法来用二进制来输出字符串,试试这个!(适用于负数)
// Important note: when parsing hexadecimal string, make sure to prefix
// with 0 if the number is positive. Ex: 0F instead of F, and 01A3 instead of 1A3.
// If the number is negative, then the first bit should be set to 1.
var x = BigInteger.Parse("0F", NumberStyles.HexNumber); // Or: BigInteger.Parse("15")
var biBytes = x.ToByteArray();
var bits = new bool [8 * biBytes.Length];
new BitArray(x.ToByteArray()).CopyTo(bits, 0);
bits = bits.Reverse().ToArray(); // BigInteger uses little endian when extracting bytes (thus bits), so we inverse them.
var builder = new StringBuilder();
foreach(var bit in bits)
{
builder.Append(bit ? '1' : '0');
}
string final = Regex.Replace(builder.ToString(), @"^0+", ""); // Because bytes consume full 8 bits, we might occasionally get leading zeros.
Console.WriteLine(final);
Output: 1111
输出:1111
#3
0
This is a simple method to convert a BigInteger
to any base:
这是一个将BigInteger转换为任何基础的简单方法:
public static string ToNBase(BigInteger a, int n)
{
StringBuilder sb = new StringBuilder();
while (a > 0)
{
sb.Insert(0,a % n);
a /= n;
}
return sb.ToString();
}
It works perfectly for base 2-10. If you want it to produce hexadecimal or other higher base strings, You have to modify a % b
's form according to the base before inserting it.
以2-10为底,效果很好。如果您希望它产生十六进制或其他更高的基本字符串,您必须根据基础修改% b的格式,然后插入它。