Кодирование числа, реализация C # z-base-32 или что-то еще? - PullRequest
11 голосов
/ 08 апреля 2009

Мне нужно кодировать / декодировать целое число длиной до 9 цифр, но чаще всего длиной 7 цифр. Я хотел бы упростить общение / запоминание - оно будет передано по телефону, скопировано и вставлено, введено с карты / памяти / этикетки, написано от руки на наклейках и, как правило, злоупотреблено!

Я пытаюсь уменьшить количество цифр (добавляя контрольную сумму), используя схему base 32 . Я больше всего поддерживаю z-base-32 (по сравнению с реализацией RFC4648 ) из-за некоторых целей проектирования (например, рукописный ввод) и выбора алфавита (строчные буквы, переставлять в пользу символов, которые легче читать, писать, говорить и помнить). Однако я не могу найти реализацию C #, и я обеспокоен портированием из существующей реализации Python.

У кого-нибудь есть реализация C #? Или у кого-нибудь есть набор тестовых случаев (кроме примеров в спецификации), которые я могу использовать для проверки порта?

Я открыт для предложений об альтернативных схемах кодирования.

Ответы [ 5 ]

9 голосов
/ 10 марта 2011

Я начал с кода, предоставленного учетной записью 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());
    }
}

А вот и тесты, которые я использовал. Тест 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);
    }
}
4 голосов
/ 08 апреля 2009

Возможно, вы захотите использовать свою собственную процедуру кодирования / декодирования?

Encode:

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

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

Decode:

 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]);
 }    

(непроверенный код)

2 голосов
/ 23 марта 2012

небольшое улучшение поста 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;
}
2 голосов
/ 08 апреля 2009

Если вы посмотрите на клавиатуру вашего мобильного телефона, номер 1985239 можно представить с помощью этих символов (a, b, c), (w, x, y, z), (t, u, v), ... Попытайтесь найти алгоритм, который генерировал бы более или менее английские слова с учетом упорядоченного набора неупорядоченных наборов символов - их будет легче запомнить.

1 голос
/ 08 апреля 2009

Этот проект выглядит так, как вы хотите:

Тип базы 36 для .NET (C #)

...