base_convert в .NET - PullRequest
       16

base_convert в .NET

5 голосов
/ 26 марта 2009

Есть ли в .NET встроенная функция, которая эквивалентна PHP base_convert , или мне нужно написать свою собственную? Я хочу преобразовать из любой базы в любую другую базу - где база «to» или база «from» могут быть любыми целыми числами от 2 до 36.

Пример функции PHP: base_convert ($ number_to_convert, $ from_base, $ to_base)

// convert 101 from binary to decimal
echo base_convert('101', 2, 10);
// 5

Как отметил Люк в комментариях к ответу Джона Скита: Convert.ToString не может обрабатывать преобразование в / из произвольной базы, только 2, 8, 10 и 16

Обновление: Судя по всему, ответ: нет, родного пути нет. Ниже Эрик показывает один из способов сделать это. Другая реализация здесь: http://www.codeproject.com/KB/macros/Convert.aspx

Ответы [ 3 ]

11 голосов
/ 26 марта 2009

РЕДАКТИРОВАТЬ: Этот ответ очень удобен, но работает только для основ 2, 8, 10 и 16

Вы можете использовать Convert.ToInt32(text, base), а затем Convert.ToString(number, base):

using System;

class Test
{
    static void Main()
    {
        int number = Convert.ToInt32("101", 2);
        string text = Convert.ToString(number, 10);
        Console.WriteLine(text); // Prints 5
    }
}

Если вы конвертируете в или из базы 10, вам не нужно указывать это - это значение по умолчанию.

Обратите внимание, что это работает только для баз 2, 8, 10 и 16. Если вам нужно что-то еще, вам придется написать свой собственный анализатор / форматер.

9 голосов
/ 26 марта 2009

Вот некоторый код, который преобразует целое число в произвольное основание до 36 и преобразует строковое представление значения x в целое (с учетом основания):

class Program {
    static void Main(string[] args) {
        int b10 = 123;
        int targetBase = 5;

        string converted = ConvertToBase(b10, targetBase);
        int convertedBack = ConvertFromBase(converted, targetBase);

        string base3 = "212210";
        string base7 = ConvertFromBaseToBase(base3, 3, 7);

        Console.WriteLine(converted);
        Console.WriteLine(convertedBack);
        Console.WriteLine(base7);
        Console.ReadLine();
    }

    private const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private static string ConvertToBase(int b10, int targetBase) {
        if (targetBase < 2) throw new ArgumentException("Target base must be greater than 2.", "targetBase");
        if (targetBase > 36) throw new ArgumentException("Target base must be less than 36.", "targetBase");

        if (targetBase == 10) return b10.ToString();

        StringBuilder result = new StringBuilder();

        while (b10 >= targetBase) {
            int mod = b10 % targetBase;
            result.Append(chars[mod]);
            b10 = b10 / targetBase;
        }

        result.Append(chars[b10]);

        return Reverse(result.ToString());
    }

    private static int ConvertFromBase(string bx, int fromBase) {
        if (fromBase < 2) throw new ArgumentException("Base must be greater than 2.", "fromBase");
        if (fromBase > 36) throw new ArgumentException("Base must be less than 36.", "fromBase");

        if (fromBase == 10) return int.Parse(bx);

        bx = Reverse(bx);
        int acc = 0;

        for (int i = 0; i < bx.Length; i++) {
            int charValue = chars.IndexOf(bx[i]);
            acc += (int)Math.Pow(fromBase, i) * charValue;
        }

        return acc;
    }

    public static string ConvertFromBaseToBase(string bx, int fromBase, int toBase) {
        int b10 = ConvertFromBase(bx, fromBase);
        return ConvertToBase(b10, toBase);
    }

    public static string Reverse(string s) {
        char[] charArray = new char[s.Length];
        int len = s.Length - 1;
        for (int i = 0; i <= len; i++)
            charArray[i] = s[len - i];
        return new string(charArray);
    }
}

Если вы не беспокоитесь об отображении этих значений, вы можете использовать расширенные символы в наборе символов - если вы придерживаетесь простого ascii, теоретически вы можете иметь значения base256. Выходя за рамки этого, я бы порекомендовал не использовать символы, а вместо этого использовать какое-то другое уникально идентифицируемое значение - хотя я не вижу большого значения.

1 голос
/ 29 июля 2009

В ConvertToBase следующая строка:

while (b10> targetBase)

... должно быть:

while (b10> = targetBase)

, который заботится о появлении базового числа в преобразованном числе (например, преобразование «3» в основание 3 дает «3» вместо «10»).

...