12

最大 9 桁の整数をエンコード/デコードする必要がありますが、ほとんどの場合は 7 桁です。コミュニケーション/記憶をより簡単にしたい - 電話で伝えられ、コピー&ペーストされ、カード/メモリー/ラベルからキー入力され、ラベルに手書きされ、一般的に悪用される.

base 32スキームを使用して(チェックサムを追加しながら)桁数を減らしたいと考えています。私は( RFC4648実装よりも) z-base-32を最も支持しています。これは、いくつかの設計目標 (手書きなど) とアルファベットの選択 (小文字、読みやすく、書きやすく、話して覚える)。しかし、C# の実装が見つからず、既存の Python 実装からの移植が心配です。

誰かがC#の実装を持っていますか? または、ポートの検証に使用できる一連のテスト ケース (仕様の例以外) を持っている人はいますか?

代替のエンコーディング スキームに関する提案を受け付けています。

4

5 に答える 5

10

Dead アカウントから提供されたコードから始めて、テストに基づいていくつかの変更を加えました。これが役に立つことを願っています。

/// <summary>
/// Author: Ben Maddox
/// </summary>
public class ZBase32Encoder
{
    /*
     * Accepted characters based on code from: 
     * http://www.codeproject.com/KB/recipes/Base32Encoding.aspx?display=Print
     */
    public const string AcceptedCharacters = "ybndrfg8ejkmcpqxot1uwisza345h769";

    public static string Encode(int input)
    {
        string result = "";

        if (input == 0)
        {
            result += AcceptedCharacters[0];
        }
        else
        {
            while (input > 0)
            {
                //Must make sure result is in the correct order
                result = AcceptedCharacters[input%AcceptedCharacters.Length] + result;
                input /= AcceptedCharacters.Length;
            }
        }

        return result;
    }

    public static int Decode(string input)
    {
        var inputString = input.ToLower();

        int result = 0;
        for (int i = 0; i < inputString.Length; i++)
        {
            result *= AcceptedCharacters.Length;
            var character = inputString[i];
            result += AcceptedCharacters.IndexOf(character);
        }
        return result;
    }

    public static int Decode(char data)
    {
        return Decode(data.ToString());
    }
}

そして、これが私が使用したテストです。Should アサーション ライブラリを使用した MS テスト。

[TestClass]
public class ZBase32EncoderTests
{

    [TestMethod]
    public void Encoding_0_ReturnsFirstCharacter()
    {
        var result = ZBase32Encoder.Encode(0);
        result.ShouldEqual(ZBase32Encoder.AcceptedCharacters[0].ToString());
    }

    [TestMethod]
    public void Encoding_1_ReturnsSecondCharacter()
    {
        var result = ZBase32Encoder.Encode(1);
        result.ShouldEqual(ZBase32Encoder.AcceptedCharacters[1].ToString());
    }

    [TestMethod]
    public void Encoding_32_ReturnsSecondAndFirstValues()
    {
        var result = ZBase32Encoder.Encode(32);
        result.ShouldEqual(ZBase32Encoder.AcceptedCharacters[1].ToString() + ZBase32Encoder.AcceptedCharacters[0].ToString());
    }

    [TestMethod]
    public void Encoding_64_ReturnsThirdAndFirstValues()
    {
        var result = ZBase32Encoder.Encode(64);
        result.ShouldEqual(ZBase32Encoder.AcceptedCharacters[2].ToString() + ZBase32Encoder.AcceptedCharacters[0].ToString());
    }

    [TestMethod]
    public void Encoding_65_ReturnsThirdAndSecondValues()
    {
        var result = ZBase32Encoder.Encode(65);
        result.ShouldEqual(ZBase32Encoder.AcceptedCharacters[2].ToString() + ZBase32Encoder.AcceptedCharacters[1].ToString());
    }



    [TestMethod]
    public void Decoding_FirstCharacter_Returns_0()
    {
        var inputCharacter = ZBase32Encoder.AcceptedCharacters[0];
        var result = ZBase32Encoder.Decode(inputCharacter);
        result.ShouldEqual(0);
    }

    [TestMethod]
    public void Decoding_SecondCharacter_Returns_1()
    {
        var inputCharacter = ZBase32Encoder.AcceptedCharacters[1];
        var result = ZBase32Encoder.Decode(inputCharacter);
        result.ShouldEqual(1);
    }

    [TestMethod]
    public void Decoding_SecondAndFirstValues_Shows_32()
    {
        var inputCharacters = ZBase32Encoder.AcceptedCharacters[1].ToString() + ZBase32Encoder.AcceptedCharacters[0];
        var result = ZBase32Encoder.Decode(inputCharacters);
        result.ShouldEqual(32);
    }

    [TestMethod]
    public void Decoding_ThirdAndFirstCharacters_Shows_64()
    {
        var inputCharacters = ZBase32Encoder.AcceptedCharacters[2].ToString() + ZBase32Encoder.AcceptedCharacters[0];
        var result = ZBase32Encoder.Decode(inputCharacters);
        result.ShouldEqual(64);
    }
}
于 2011-03-10T03:19:31.530 に答える
6

独自のエンコード/デコード ルーチンを使用したい場合がありますか?

エンコード:

 string acceptedChar = "ABCDEFGHJKLMNPQRSTUWXZ0123456789";
 int yourNumber = 12345678;

 string response = "";
 while (yourNumber > 0)
 {
      response += acceptedChar[yourNumber % acceptedChar.Length];
      yourNumber /= acceptedChar.Length;
 }

デコード:

 string acceptedChar = "ABCDEFGHJKLMNPQRSTUWXZ0123456789";
 string inputStr = "ABCD";

 int yourNumber = 0;
 for (int i = inputStr.Length; i > 0; i--)
 {
     yourNumber *= acceptedChar.Length;
     yourNumber += acceptedChar.IndexOf(inputStr[i]);
 }    

(未テストのコード)

于 2009-04-08T09:47:58.670 に答える
2

BenMaddoxの投稿のわずかな改善(do-whileを使用):

public static String encode(int num, String base) {
    String response = "";
    do{
        response = base.charAt(num % base.length()) + response;
        num /= base.length();
    } while(num>0); 
    return response;
}
于 2012-03-23T01:11:09.367 に答える
2

携帯電話のキーボードを見ると、1985239 という数字は (a、b、c)、(w、x、y、z)、(t、u、v)、...順序付けされていない文字セットの順序付けられたセットが与えられると、多かれ少なかれ英語に似た単語を生成するアルゴリズム - これらは覚えやすくなります。

于 2009-04-08T09:47:52.383 に答える