jos*_*ley 103 .net c# int base number-systems
我有和旧的(ish)C#方法我写了一个数字并将其转换为任何基数:
string ConvertToBase(int number, char[] baseChars);
Run Code Online (Sandbox Code Playgroud)
它不是那么超级快速和整洁.在.NET中有没有一种很好的,已知的方法来实现这一点?
我在寻找的东西,让我使用任何基地要使用的字符的任意字符串.
这只允许碱基16,10,8和2:
Convert.ToString(1, x);
Run Code Online (Sandbox Code Playgroud)
我想利用它来利用数字,全部小写和全部大写字母来实现高基数.就像在这个线程中一样,但对于C#而不是JavaScript.
有谁知道在C#中这样做的好方法?
Dir*_*mar 127
Convert.ToString 可用于将数字转换为指定基数中的等效字符串表示形式.
例:
string binary = Convert.ToString(5, 2); // convert 5 to its binary representation
Console.WriteLine(binary); // prints 101
Run Code Online (Sandbox Code Playgroud)
然而,正如评论所指出的,Convert.ToString只支持以下有限的 - 但通常是足够的 - 基础集:2,8,10或16.
我不知道BCL中的任何方法能够将数字转换为任何基数,因此您必须编写自己的小实用程序函数.一个简单的示例看起来就像那样(请注意,通过替换字符串连接可以更快地完成此操作):
class Program
{
static void Main(string[] args)
{
// convert to binary
string binary = IntToString(42, new char[] { '0', '1' });
// convert to hexadecimal
string hex = IntToString(42,
new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'});
// convert to hexavigesimal (base 26, A-Z)
string hexavigesimal = IntToString(42,
Enumerable.Range('A', 26).Select(x => (char)x).ToArray());
// convert to sexagesimal
string xx = IntToString(42,
new char[] { '0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x'});
}
public static string IntToString(int value, char[] baseChars)
{
string result = string.Empty;
int targetBase = baseChars.Length;
do
{
result = baseChars[value % targetBase] + result;
value = value / targetBase;
}
while (value > 0);
return result;
}
/// <summary>
/// An optimized method using an array as buffer instead of
/// string concatenation. This is faster for return values having
/// a length > 1.
/// </summary>
public static string IntToStringFast(int value, char[] baseChars)
{
// 32 is the worst cast buffer size for base 2 and int.MaxValue
int i = 32;
char[] buffer = new char[i];
int targetBase= baseChars.Length;
do
{
buffer[--i] = baseChars[value % targetBase];
value = value / targetBase;
}
while (value > 0);
char[] result = new char[32 - i];
Array.Copy(buffer, i, result, 0, 32 - i);
return new string(result);
}
}
Run Code Online (Sandbox Code Playgroud)
使用数组缓冲区而不是字符串连接来构建结果字符串可以提高性能,特别是对于大数字(参见方法IntToStringFast).在最好的情况下(即最长的输入),这种方法大约快三倍.但是,对于1位数字(即目标基数中的1位数字),IntToString会更快.
Pav*_*dov 72
我最近在博客上写了这个.我的实现在计算过程中不使用任何字符串操作,这使得它非常快.支持转换为基数为2到36的任何数字系统:
/// <summary>
/// Converts the given decimal number to the numeral system with the
/// specified radix (in the range [2, 36]).
/// </summary>
/// <param name="decimalNumber">The number to convert.</param>
/// <param name="radix">The radix of the destination numeral system (in the range [2, 36]).</param>
/// <returns></returns>
public static string DecimalToArbitrarySystem(long decimalNumber, int radix)
{
const int BitsInLong = 64;
const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (radix < 2 || radix > Digits.Length)
throw new ArgumentException("The radix must be >= 2 and <= " + Digits.Length.ToString());
if (decimalNumber == 0)
return "0";
int index = BitsInLong - 1;
long currentNumber = Math.Abs(decimalNumber);
char[] charArray = new char[BitsInLong];
while (currentNumber != 0)
{
int remainder = (int)(currentNumber % radix);
charArray[index--] = Digits[remainder];
currentNumber = currentNumber / radix;
}
string result = new String(charArray, index + 1, BitsInLong - index - 1);
if (decimalNumber < 0)
{
result = "-" + result;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我也实现了一个快速反函数,以防任何人需要它: 任意到十进制数字系统.
快速" 从 "和" 到 "方法
我迟到了,但是我把以前的答案复合了,并对它们进行了改进.我认为这两种方法比目前为止发布的其他方法都快.我能够在单核心机器中将400,000个数字转换为400以下的基数36.
以下示例适用于基座62.更改BaseChars阵列以从任何其他基础转换为.
private static readonly char[] BaseChars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
private static readonly Dictionary<char, int> CharValues = BaseChars
.Select((c,i)=>new {Char=c, Index=i})
.ToDictionary(c=>c.Char,c=>c.Index);
public static string LongToBase(long value)
{
long targetBase = BaseChars.Length;
// Determine exact number of characters to use.
char[] buffer = new char[Math.Max(
(int) Math.Ceiling(Math.Log(value + 1, targetBase)), 1)];
var i = buffer.Length;
do
{
buffer[--i] = BaseChars[value % targetBase];
value = value / targetBase;
}
while (value > 0);
return new string(buffer, i, buffer.Length - i);
}
public static long BaseToLong(string number)
{
char[] chrs = number.ToCharArray();
int m = chrs.Length - 1;
int n = BaseChars.Length, x;
long result = 0;
for (int i = 0; i < chrs.Length; i++)
{
x = CharValues[ chrs[i] ];
result += x * (long)Math.Pow(n, m--);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
编辑(2018-07-12)
修复以解决由@AdrianBotor(请参阅注释)将46655转换为基数36所发现的极端情况.这是由一个小的浮点错误计算引起的,它Math.Log(46656, 36)正好是3,但.NET返回3 + 4.44e-16,这会在输出缓冲区中产生额外的字符.
也可以使用已接受的版本的略微修改版本,并根据需要调整基本字符串:
public static string Int32ToString(int value, int toBase)
{
string result = string.Empty;
do
{
result = "0123456789ABCDEF"[value % toBase] + result;
value /= toBase;
}
while (value > 0);
return result;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
118230 次 |
| 最近记录: |