出力が衝突するため、ランダムな部分文字列に基づいた解は良くありません。それは時期尚早に(不運を伴って)起こる可能性があり、生成された値のリストが大きくなると最終的に発生します。衝突の可能性が高くなるほど大きなものである必要はありません(birthday attack参照)。
この問題には、URLに表示される増分IDと対応するIDの間にpseudo random permutationがあります。この技術は、入力空間と同じくらい小さい出力空間に生成しながら、衝突が不可能であることを保証します。
実装
Iは32ビットブロック、3ラウンドと擬似乱数発生器触発されラウンド関数とFeistel cipherのこのC#バージョンを示唆しています。
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 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);
}
は、base62文字列に並べ替えIDを発現させるために:
private static string GenerateCode(uint id)
{
return ToBase62(PermuteId(id));
}
Base62
機能が同じであることを除いてthe previous answerがそうでなければ、これらの機能は、に書き換えなければならない(uint
代わりにint
をとるよう負の値を扱う)。アルゴリズム
RoundFunction
をカスタマイズ
は、アルゴリズムの秘密のソースです。秘密鍵を含む非公開のバージョンに変更することができます。 Feistel構造は、2つの非常に素敵なプロパティがあります。
は注意してください、それがまだ各PermuteId
出力の独自の観点で働くだろうが、擬似ランダム効果を台無しにラウンド式にあまりにも些細な何かを置きます。また、数学的な意味での関数ではない式はアルゴリズムと互換性がないので、例えばrandom()
を含むものは許されません。
Reversability
現在の形で、PermuteId
機能があることを意味し、独自の逆数、である:あなたが戻ってそれを変換する場合
PermuteId(PermuteId(id))==id
だから、プログラムによって生成短い文字列を与えられましたFromBase62
関数を持つuint
に変換し、対応する初期IDを返すPermuteId()
への入力として与えます。 [internal-ID/shortstring]関係を格納するデータベースがない場合、これはかなりクールです。実際には格納する必要はありません!
製造も短いストリング
上記機能の範囲は、0から2^32-1
約40億の値であり、32ビットです。その範囲をbase62で表現するには、6文字が必要です。
わずか5文字で、最大で62^5
の値を表すことができます(これは10億を少し下回ります)。出力文字列が5つの文字に制限する必要があり、次のように、コードを微調整する必要があります。
N
は、このようなN
が偶数で、2^N
はできるだけ高いが62^5
よりも低くなっていることがわかります。それは28だから、62^5
に収まる実際の出力範囲は2^28
または約2億6800万の値になるでしょう。 PermuteId
に
、に注意しては(2^28未満でなければならない)入力の単一のビットを無視していないが、代わりに16ビットでl1
とr1
28/2=14
ためのビット値を使用します。
RoundFunction
の結果に65535の代わりに16383を掛けて、14ビットの範囲内にとどまる。 PermuteId
の終わりに
- 、
r1
とl1
は2^22
の出力範囲で、代わりに32と同様の方法で4つの文字に適用することができる
の14+14=28
ビット値を形成するために再結合し、又は約400万の価値。
が、それは上記のバージョンでは
のように何を求めず、最初の10は、ID = 1で始まる文字列が生成されます
cZ6ahF
3t5mM
xGNPN
dxwUdS
ej9SyV
cmbVG3
cOlRkc
bfCPOX
JDr8Q
eg7iuA
私はラウンド関数内の些細な変更を加えた場合、それは次のようになります。
ey0LlY
ddy0ak
dDw3wm
bVuNbg
bKGX22
c0s5GZ
dfNMSp
ZySqE
cxKH4b
dNqMDA
は、このページに解答の読み取りを持っている:http://stackoverflow.com/questions/3193000/how-does-tiny-url-work – Ste
あなたはGUIDよりも小さいはずの小さいランダムな英数字コードを生成したいですか?他の制約はありませんか? – Clueless
@Clueless:データベース内の主キーと重複しない長さでなければなりません。 – capdragon