簡體   English   中英

將 UInt64 表示為字符串的最短方法

[英]Shortest way to represent UInt64 as a string

我得到一個可能很大的數字 (UInt.MaxValue: 18446744073709551615) 作為一個正常的 base10 數字。 這個數字最終會成為一個文件名:12345678945768.txt

由於 Windows 上的文件名不僅限於數字,我想將其“壓縮”為較短的字符串,但需要確保字符串可以映射回數字。

對於較小的數字:0001365555,十六進制比其他任何東西都要短得多。 到目前為止,我發現的所有內容都表明 Base64 是最短的,但事實並非如此。

到目前為止,我已經嘗試過這個:

//18446744073709551615 - 20
UInt64 i = UInt64.MaxValue; // 0001365555

//"//////////8=" - 12
string encoded = Convert.ToBase64String(BitConverter.GetBytes(i)); 

//"FFFFFFFFFFFFFFFF" - 16
string hexed = i.ToString("X"); 

//"MTg0NDY3NDQwNzM3MDk1NTE2MTU=" - 28
string utf = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(i.ToString())); 

有沒有更好的方法來“壓縮”整數以轉換類似於十六進制但使用 00-zz 而不僅僅是 00-FF?

提前致謝!

到目前為止,我發現的所有內容都表明 Base64 是最短的,但事實並非如此。

您不想使用 Base64。 Base64 編碼的文本可以使用/字符,這在 Windows 上的文件名中是不允許的。 你需要想出別的辦法。

還有什么?

好吧,您可以編寫自己的基本轉換,可能是這樣的:

public static string Convert(ulong number)
{
    var validCharacters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&()_-";
    char[] charArray = validCharacters.ToCharArray();
    var buffer = new StringBuilder();
    var quotient = number;
    ulong remainder;
    while (quotient != 0)
    {
        remainder = quotient % (ulong)charArray.LongLength;
        quotient = quotient / (ulong)charArray.LongLength;
        buffer.Insert(0, charArray[remainder].ToString());
    }
    return buffer.ToString();
}

這是一個“base-73”結果, validCharacters字符越多,輸出越小。 隨意添加更多內容,只要它們在您的文件系統中是合法字符即可。

你允許的字符集是什么? 如果您可以識別 7132 個可以安全使用的不同 Unicode 字符,則可以將 64 位數字編碼為五個 Unicode 字符。 另一方面,並​​非所有文件系統都支持此類字符。 如果可以識別 139 個合法字符,則可以將數據壓縮為 9 個字符的字符串。 使用 85,您可以使用十個字符的字符串。

你誤用了 Base64。

(System.Text.Encoding.ASCII.GetBytes(i.ToString())

這會生成一個字節序列,其中包含 base10 編碼的整數,並在 base64 中再次對其進行編碼。 這顯然是低效的。

您需要獲取整數的原始字節並使用 base64 對其進行編碼。 哪種編碼最有效取決於您想要允許的字符數。 如果你想要笑

並且您應該在數組的一側修剪 0 個字節。

var bytes=BitConverter.GetBytes(input);
int len=8;
for(int i=7;i>=0;i--)
{
  if(bytes[i]!=0)
  {
    len=i+1;
    break;
  }
}
string s=Convert.ToBase64String(bytes,0,len).ReplaceString('/','-');

請注意,這在大端系統上不會按預期工作。

但也許您應該避免使用字節編碼,而只使用基數更高的整數編碼。

一個簡單的版本可能是:

string digitChars="0123..."
while(i!=0)
{
  int digit=i%digitChars.Length;
  i/=digitChars.Length;
  result=digitChars[digit]+result;
}

這是一些使用上面 vcsjones 答案的代碼,但也包括反向轉換。 就像他的回答一樣,如果需要減少字符串大小,請隨意添加更多字符。 下面的字符為 ulong.MaxValue 生成大小為 13 的字符串。

private const string _conversionCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

public static string UlongToCompressedString(ulong number)
{
    char[] charArray = _conversionCharacters.ToCharArray();
    var buffer = new System.Text.StringBuilder();
    var quotient = number;
    ulong remainder;
    while (quotient != 0)
    {
        remainder = quotient % (ulong)charArray.LongLength;
        quotient = quotient / (ulong)charArray.LongLength;
        buffer.Insert(0, charArray[remainder].ToString());
    }
    return buffer.ToString();
}

public static ulong? CompressedStringToULong(string compressedNumber)
{
    if (compressedNumber == null)
        return null;

    if (compressedNumber.Length == 0))
        return 0;

    ulong result   = 0;
    int   baseNum  = _conversionCharacters.Length;
    ulong baseMult = 1;

    for (int i=compressedNumber.Length-1; i>=0; i--)
    {
        int cPos = _conversionCharacters.IndexOf(compressedNumber[i]);
        if (cPos < 0)
            return null;
        result += baseMult * (ulong)cPos;
        baseMult *= (ulong)baseNum;
    }

    return result;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM