我需要将一个整数转换为base64字符表示。我正在使用OxA3在这个主题上的答案:Quickest way to convert a base 10 number to any base in .NET?
如何反向操作以获得原始整数,给定一个字符串?
Joel Mueller的回答应该能指导你处理base-64的情况。
针对你在你自己的回答中提供的初步代码,你可以通过改变代码实现你的for
循环(实际上是一个O(N)的IndexOf
)来提高效率,使用哈希查找(这应该使它成为O(1))。
我基于以下假设进行此操作:baseChars
是你在类构造函数中初始化的字段。如果正确,请进行以下调整:
private Dictionary<char, int> baseChars;
// I don't know what your class is called.
public MultipleBaseNumberFormatter(IEnumerable<char> baseCharacters)
{
// check for baseCharacters != null and Count > 0
baseChars = baseCharacters
.Select((c, i) => new { Value = c, Index = i })
.ToDictionary(x => x.Value, x => x.Index);
}
StringToInt
方法中:char next = encodedString[currentChar];
// No enumerating -- we've gone from O(N) to O(1)!
if (!characterIndices.TryGetValue(next, out nextCharIndex))
{
throw new ArgumentException("Input includes illegal characters.");
}
我这里有一个初步的可用版本,但我不确定它的效率如何。
public static int StringToInt(string encodedString, char[] baseChars)
{
int result = 0;
int sourceBase = baseChars.Length;
int nextCharIndex = 0;
for (int currentChar = encodedString.Length - 1; currentChar >= 0; currentChar--)
{
char next = encodedString[currentChar];
// For loop gets us: baseChar.IndexOf(char) => int
for (nextCharIndex = 0; nextCharIndex < baseChars.Length; nextCharIndex++)
{
if (baseChars[nextCharIndex] == next)
{
break;
}
}
// For character N (from the end of the string), we multiply our value
// by 64^N. eg. if we have "CE" in hex, F = 16 * 13.
result += (int)Math.Pow(baseChars.Length, encodedString.Length - 1 - currentChar) * nextCharIndex;
}
return result;
}
以下是使用 Linq 功能和 .NET Framework 4.0 的 Zip 扩展来执行计算的版本。
public static int StringToInt(string encodedString, char[] baseChars) {
int sourceBase = baseChars.Length;
var dict = baseChars
.Select((c, i) => new { Value = c, Index = i })
.ToDictionary(x => x.Value, x => x.Index);
return encodedString.ToCharArray()
// Get a list of positional weights in descending order, calcuate value of weighted position
.Zip(Enumerable.Range(0,encodedString.Length).Reverse(), (f,s) => dict[f] * (int)Math.Pow(sourceBase,s))
.Sum();
}
提醒一下,如果需要大量转换,事先在函数外计算字典会更有效率。
public class Program
{
public static void Main()
{
int i = 100;
Console.WriteLine("Int: " + i);
// Default base definition. By moving chars around in this string, we can further prevent
// users from guessing identifiers.
var baseDefinition = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//var baseDefinition = "WBUR17GHO8FLZIA059M4TESD2VCNQKXPJ63Y"; // scrambled to minimize guessability
// Convert base10 to baseK
var newId = ConvertToBaseK(i, baseDefinition);
Console.WriteLine(string.Format("To base{0} (short): {1}", baseDefinition.Length, newId));
// Convert baseK to base10
var convertedInt2 = ConvertToBase10(newId, baseDefinition);
Console.WriteLine(string.Format("Converted back: {0}", convertedInt2));
}
public static string ConvertToBaseK(int val, string baseDef)
{
string result = string.Empty;
int targetBase = baseDef.Length;
do
{
result = baseDef[val % targetBase] + result;
val = val / targetBase;
}
while (val > 0);
return result;
}
public static int ConvertToBase10(string str, string baseDef)
{
double result = 0;
for (int idx = 0; idx < str.Length; idx++)
{
var idxOfChar = baseDef.IndexOf(str[idx]);
result += idxOfChar * System.Math.Pow(baseDef.Length, (str.Length-1) - idx);
}
return (int)result;
}
}
int orig = 1337;
byte[] origBytes = BitConverter.GetBytes(orig);
string encoded = Convert.ToBase64String(origBytes);
byte[] decoded = Convert.FromBase64String(encoded);
int converted = BitConverter.ToInt32(decoded, 0);
System.Diagnostics.Debug.Assert(orig == converted);