26

goo.gljsfiddle のWeb サイト ( )のようなコードを生成したいと考えていますhttp://jsfiddle.net/XzKvP/

GUIDが大きすぎる、英数字コードの繰り返しなど、さまざまなことを試しました。

データベース テーブルの主キーに基づいて英数字コードを生成できるはずだと考えています。このようにして、繰り返されなくなりますか?PK は、1 ずつ自動インクリメントされる整数です。しかし、それがどのように行われるべきかはわかりません。

コードをランダムに見せたいのですが、そうである必要はありません。たとえば、データベース内のアイテムを に、アイテムをにしたくありません1234BCDE1235BCDF

例:

http://jsfiddle.net/XzKvP/ページに関連付けられた一意の 5 文字のコードがURL に含まれていることに注目XzKvPしてください。同じタイプのコードを生成できるようにしたい。

goo.gl もそれを行います: http://goo.gl/UEhtg hasUEhtg

これはどのように行われますか?

4

3 に答える 3

10

5 文字のコードは、base-62 表記の数字と考えることができます。「数字」は、26 個の小文字と 26 個の大文字、および 0 から 9 までの数字です。合計で (26+26+10) 桁です。0 から62^5(916132832 に等しい) までの数値 (たとえば、主キー) を指定すると、次のように 5 桁の base-62 に変換できます。

private static char Base62Digit(int d) {
    if (d < 26) {
        return (char)('a'+d);
    } else if (d < 52) {
        return (char)('A'+d-26);
    } else if (d < 62) {
        return (char)('0'+d-52);
    } else {
        throw new ArgumentException("d");
    }
}

static string ToBase62(int n) {
    var res = "";
    while (n != 0) {
        res = Base62Digit(n%62) + res;
        n /= 62;
    }
    return res;
}

private static int Base62Decode(char c) {
    if (c >= '0' && c <= '9') {
        return 52 + c - '0';
    } else if (c >= 'A' && c <= 'Z') {
        return 26 + c - 'A';
    } else if (c >= 'a' && c <= 'z') {
        return c - 'a';
    } else {
        throw new ArgumentException("c");
    }
}

static int FromBase62(string s) {
    return s.Aggregate(0, (current, c) => current*62 + Base62Decode(c));
}

暗号的に強力な乱数を生成する方法は次のとおりです ( への参照を追加する必要がありますSystem.Security)。

private static readonly RNGCryptoServiceProvider crypto =
    new RNGCryptoServiceProvider();

private static int NextRandom() {
    var buf = new byte[4];
    crypto.GetBytes(buf);
    return buf.Aggregate(0, (p, v) => (p << 8) + v) & 0x3FFFFFFF;
}
于 2012-04-24T14:29:28.280 に答える
3

これは私がやったことです

(DanielVéritéの回答以降に更新):

class Program
{

    private static double RoundFunction(uint input)
    {
        // Must be a function in the mathematical sense (x=y implies f(x)=f(y))
        // but it doesn't have to be reversible.
        // Must return a value between 0 and 1
        return ((1369 * input + 150889) % 714025) / 714025.0;
    }
    private static char Base62Digit(uint d)
    {
        if (d < 26)
        {
            return (char)('a' + d);
        }
        else if (d < 52)
        {
            return (char)('A' + d - 26);
        }
        else if (d < 62)
        {
            return (char)('0' + d - 52);
        }
        else
        {
            throw new ArgumentException("d");
        }
    }
    private static string ToBase62(uint n)
    {
        var res = "";
        while (n != 0)
        {
            res = Base62Digit(n % 62) + res;
            n /= 62;
        }
        return res;
    }
    private static uint PermuteId(uint id)
    {
        uint l1 = (id >> 16) & 65535;
        uint r1 = id & 65535;
        uint l2, r2;
        for (int i = 0; i < 3; i++)
        {
            l2 = r1;
            r2 = l1 ^ (uint)(RoundFunction(r1) * 65535);
            l1 = l2;
            r1 = r2;
        }
        return ((r1 << 16) + l1);
    }


    private static string GenerateCode(uint id)
    {
        return ToBase62(PermuteId(id));
    }

    static void Main(string[] args)
    {

        Console.WriteLine("testing...");

            try
            {

                for (uint x = 1; x < 1000000; x += 1)
                {
                    Console.Write(GenerateCode(x) + ",");

                }

            }
            catch (Exception err)
            {
                Console.WriteLine("error: " + err.Message);
            }

        Console.WriteLine("");
        Console.WriteLine("Press 'Enter' to continue...");
        Console.Read();
    }
}
于 2012-04-24T17:30:49.060 に答える