md5 文字列 (base 16) を c++ で base 62 文字列に変換しようとしています。base 62 に変換するためにこれまでに見つけたすべてのソリューションは、数値を 64 ビット整数以下で表すことができる場合にのみ機能します。md5 文字列は 128 ビットで、私はこれでどこにも行きません。
bigint ライブラリをインクルードして、それで終了する必要がありますか?
簡単にするために、私の uint128_t C++ クラス ( http://www.codef00.com/code/uint128.h ) を使用できます。これを使用すると、基本コンバーターは次のように非常に単純になります。
#include "uint128.h"
#include <iostream>
#include <algorithm>
int main() {
char a[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
uint128_t x = U128_C(0x130eb6003540debd012d96ce69453aed);
std::string r;
r.reserve(22); // shouldn't result in more than 22 chars
// 6-bits per 62-bit value means (128 / 6 == 21.3)
while(x != 0) {
r += a[(x % 62).to_integer()];
x /= 62;
}
// when converting bases by division, the digits are reversed...fix that :-)
std::reverse(r.begin(), r.end());
std::cout << r << std::endl;
}
これは以下を出力します:
J7JWEJ0YbMGqaJFCGkUxZ
どれどれ。128/log2(62)=21.497. つまり、base-62 表現には 22 の「数字」が必要です。
22 文字を超えず、62 を超える異なる文字を使用しない文字列表現だけに関心がある場合は、本当の base-62 表現は必要ありません。128 ビットを小さな断片に分割し、断片を個別にコーディングできます。この方法では、128 ビット演算は必要ありません。128 ビットを 2x64 ビットに分割し、各 64 ビット チャンクを長さ 11 の文字列でエンコードすることができます。これは、わずか 57 文字の異なる文字でも可能です。したがって、「視覚的なあいまいさ」を避けるために、62 文字のうち 5 文字を削除することができます。たとえば、l,1,B,8 を削除します。これにより、58 個の異なる文字と 11*log2(58)=64.438 が残り、これは 64 ビットをエンコードするのにちょうど十分です。
2 つの 64 ビット チャンクを取得するのはそれほど難しくありません。
#include <climits>
#if CHAR_BIT != 8
#error "platform not supported, CHAR_BIT==8 expected"
#endif
// 'long long' is not yet part of C++
// But it's usually a supported extension
typedef unsigned long long uint64;
uint64 bits2uint64_bigendian(unsigned char const buff[]) {
return (static_cast<uint64>(buff[0]) << 56)
| (static_cast<uint64>(buff[1]) << 48)
| (static_cast<uint64>(buff[2]) << 40)
| (static_cast<uint64>(buff[3]) << 32)
| (static_cast<uint64>(buff[4]) << 24)
| (static_cast<uint64>(buff[5]) << 16)
| (static_cast<uint64>(buff[6]) << 8)
| static_cast<uint64>(buff[7]);
}
int main() {
unsigned char md5sum[16] = {...};
uint64 hi = bits2uint64_bigendian(md5sum);
uint64 lo = bits2uint64_bigendian(md5sum+8);
}
GMPは、任意精度の整数に便利なC++バインディングを提供します