1. ホーム
  2. c#

[解決済み] .NETで10進数を任意の進数に変換する最速の方法とは?

2022-07-17 10:12:47

質問

私が書いた古い(と思われる)C#メソッドがあり、それは数値を受け取り、任意のベースに変換します。

string ConvertToBase(int number, char[] baseChars);

超スピードですっきりとはいきませんね。.NETでこれを実現する良い既知の方法はないのでしょうか?

私は何かを探しているのですが、それは私が を使用できるものを探しています。 ベースに任意の文字列を指定して使用できるものを探しています。

これは、ベース16、10、8、2のみを許可します。

Convert.ToString(1, x);

これを利用して、数字、すべて小文字、すべて大文字を駆使して、大量にベースを実現したい。例えば このスレッド のように、しかしJavaScriptではなくC#のために。

誰かC#でこれを行うための良い、効率的な方法を知っていますか?

どのように解決するのですか?

Convert.ToString は、数値を指定された基数の等価な文字列表現に変換するために使用することができます。

の例です。

string binary = Convert.ToString(5, 2); // convert 5 to its binary representation
Console.WriteLine(binary);              // prints 101

しかし、コメントで指摘されているように Convert.ToString は以下の限られた-しかし典型的には十分な-塩基のセットをサポートするだけです: 2, 8, 10, または 16。

更新 (任意のベースに変換する要件を満たすため)。

私はBCLに数値を任意のベースに変換できるメソッドを知らないので、あなた自身の小さなユーティリティ関数を書く必要があります。簡単なサンプルは次のようなものです(文字列の連結を置き換えることで、確実に高速化できることに注意してください)。

class Program
{
    static void Main(string[] args)
    {
        // convert to binary
        string binary = IntToString(42, new char[] { '0', '1' });

        // convert to hexadecimal
        string hex = IntToString(42, 
            new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                         'A', 'B', 'C', 'D', 'E', 'F'});

        // convert to hexavigesimal (base 26, A-Z)
        string hexavigesimal = IntToString(42, 
            Enumerable.Range('A', 26).Select(x => (char)x).ToArray());

        // convert to sexagesimal
        string xx = IntToString(42, 
            new char[] { '0','1','2','3','4','5','6','7','8','9',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x'});
    }

    public static string IntToString(int value, char[] baseChars)
    {
        string result = string.Empty;
        int targetBase = baseChars.Length;

        do
        {
            result = baseChars[value % targetBase] + result;
            value = value / targetBase;
        } 
        while (value > 0);

        return result;
    }

    /// <summary>
    /// An optimized method using an array as buffer instead of 
    /// string concatenation. This is faster for return values having 
    /// a length > 1.
    /// </summary>
    public static string IntToStringFast(int value, char[] baseChars)
    {
        // 32 is the worst cast buffer size for base 2 and int.MaxValue
        int i = 32;
        char[] buffer = new char[i];
        int targetBase= baseChars.Length;

        do
        {
            buffer[--i] = baseChars[value % targetBase];
            value = value / targetBase;
        }
        while (value > 0);

        char[] result = new char[32 - i];
        Array.Copy(buffer, i, result, 0, 32 - i);

        return new string(result);
    }
}

アップデート2(性能改善)

文字列の連結の代わりに配列バッファを使用して結果の文字列を作成することで、特に大きな数でパフォーマンスが向上します ( IntToStringFast ). 最良の場合(すなわち、可能な限り長い入力)、この方法はおよそ3倍速くなります。しかし、1桁の数字(つまり、ターゲットの基数の1桁)に対しては IntToString の方が速くなります。