问题描述
在Java中,我能做到
In Java, I could do
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
在C#中,我可以做
int num = int.Parse(b.ToString());
Convert.ToString(num,2) //binary
Convert.ToString(num,8) //octal
等。
但我只能用长
值和较小的做到这一点。有打印的BigInteger与指定的基本某种方法?我,,昨天张贴了这个并获得如何解决转换基本上所有字符串的BigInteger值,但还没有成功的输出。
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 bigint = BigInteger.Parse("123456789012345678901234567890");
基地10和基地16
内置底座10(十进制)和基16(十六进制)coversions很简单:
Base 10 and Base 16
The built-in Base 10 (decimal) and base 16 (hexadecimal) coversions are easy:
// Convert to base 10 (decimal):
string base10 = bigint.ToString();
// Convert to base 16 (hexadecimal):
string base16 = bigint.ToString("X");
前导零(正与负的BigInteger值)
记,即的ToString(X)
确保十六进制字符串有一个前导零,当值的BigInteger
是正的。这与通常的行为的ToString(X),从那里前导零燮pressed其他值类型转换时
。
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.
例如:
var positiveBigInt = new BigInteger(128);
var negativeBigInt = new BigInteger(-128);
Console.WriteLine(positiveBigInt.ToString("X"));
Console.WriteLine(negativeBigInt.ToString("X"));
结果:
080
80
有对这种行为目的作为国内领先的零指示的BigInteger
是一个正值 - 本质上,领先的提供零的符号。这是必要的(相对于其它值类型转换),因为一个的BigInteger
不具有固定的大小;因此,不存在指定的符号位。前导零标识为正值,而不是一个负一。这样就可以往返的BigInteger
到到和回>解析()
。这种行为是页讨论。
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
实例,以二进制,十六进制和八进制字符串类:
Here is a class containing extension methods to convert BigInteger
instances to binary, hexadecimal, and octal strings:
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();
}
}
在乍一看,这些方法可能看起来比必要更复杂。额外的复杂性有一点,着实增加,以确保正确前导零是在转换后的字符串present。
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
转换为二进制字符串:
Here is how to use this extension method to convert a BigInteger
to a binary string:
// Convert BigInteger to binary string.
bigint.ToBinaryString();
每一种扩展方法的基本核心是 BigInteger.ToByteArray()
方法。此方法转换一个的BigInteger
字节数组,这是我们如何能够得到一个二进制重新presentation 的BigInteger
值:
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:
var bytes = bigint.ToByteArray();
要小心,不过,返回的字节数组是little-endian顺序,所以第一个数组元素是的BigInteger
最不显著字节(LSB)。由于的StringBuilder
用于构建输出字符串 - 它开始在最显著位(MSB) - 字节数组必须在反向迭代,以使最显著字节首先被转换。
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.
因此,一个索引指针被设置到字节数组中的最显著位(最后一个元素):
Thus, an index pointer is set to the most significant digit (the last element) in the byte array:
var idx = bytes.Length - 1;
要捕捉转换的字节,一个的StringBuilder
创建
To capture the converted bytes, a StringBuilder
is created:
var base2 = new StringBuilder(bytes.Length * 8);
的的StringBuilder
构造函数的的StringBuilder
的能力。所需转换八乘以的StringBuilder
通过取的字节数计算的能力(有八个二进制数字转换,从每个字节的结果)。
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).
然后,第一字节被转换成一个二进制串:
The first byte is then converted to a binary string:
var binary = Convert.ToString(bytes[idx], 2);
在这一点上,有必要确保前导零的存在,如果的BigInteger
为正值(见上述讨论)。如果第一个转换后的数字是不是一个零和 BIGINT
为正,那么 0
追加到的StringBuilder
:
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
:
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
接着,将转换后的字节附加到的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'));
}
注意,每个转换的字节被填充在左边与在必要的零(0),以使转换后的字符串是八个二进制字符。这是极其重要的。如果没有这种填充,十六进制值101将被转换成11的二进制值。前导零确保转换是'100000001'。
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'.
在所有字节转换,在的StringBuilder
包含完整的二进制字符串,它是由扩展方法返回的:
When all bytes are converted, the StringBuilder
contains the complete binary string, which is returned by the extension method:
return base2.ToString();
BigInteger.ToOctalString
转换一个的BigInteger
来一个八进制(基数8)字符串更加复杂。现在的问题是重新present八进制数字三位它不是一个甚至多个由 BigInteger.ToByteArray()
创建的字节数组中的每个元素举行的八位。为了解决这个问题,从数组三个字节被组合成的24位的块。每个24位块均匀地转换到八进制字符。
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.
第24位的块需要一定的数学模:
The first 24-bit chunk requires some modulo math:
var extra = bytes.Length % 3;
此计算确定多少字节时,整个字节数组分为三个字节(24位)的块是额外。第一次转换为八进制(最-显著位)获得额外的字节,这样所有剩余的转换将各自获得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.
如果没有额外字节,则第一个块获得一个完整的三个字节:
If there are no "extra" bytes, then the first chunk gets a full three bytes:
if (extra == 0)
{
extra = 3;
}
第一个块被加载到 INT24
称为一个整型变量,最多可容纳24位。组块的每个字节是负载。随着更多的字节加载,在 INT24
的previous位由8位左移,以腾出空间:
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:
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
24位块为八进制的转换是通过完成:
Conversion of a 24-bit chunk to octal is accomplished by:
var octal = Convert.ToString(int24, 8);
此外,第一位必须是一个前导零如果的BigInteger
是一个正值:
// Ensure leading zero exists if value is positive.
if (octal[0] != '0' && bigint.Sign == 1)
{
base8.Append('0');
}
第一变换块被追加到的StringBuilder
:
base8.Append(octal);
其余的24位的块被转换成在一个循环
The remaining 24-bit chunks are converted in a loop:
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'));
}
像二进制转换,转换后的每个八进制字符串左侧填充零,使'7'变成'00000007'。这保证了零将不会从转换的字符串(即,'17'而不是'100000007')
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').
转换一个的BigInteger
其他一些基地可能会复杂得多。只要数基是两个(即,2,4,8,16)由 BigInteger.ToByteArray()创建的字节数组
可以适当地分割成一个功率比特块和转换。
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的幂时,问题就变得更加复杂,并且需要循环和分裂的一个很好的协议。因此基数转换是罕见的,我只涵盖了流行的数字计算基地在这里。
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.
这篇关于BigInteger的为十六进制/十进制/八进制/二进制字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!