そのようなことを実装することは完全な悪夢であるため、作業する何らかのbignum除算/モジュロ関数が既にあると仮定します。
class bignum {
public:
bignum(unsigned value=0);
bignum(const bignum& rhs);
bignum(bignum&& rhs);
void divide(const bignum& denominator, bignum& out_modulo);
explicit operator bool();
explicit operator unsigned();
};
std::ostream& operator<<(std::ostream& out, bignum value) {
std::string backwards;
bignum remainder;
do {
value.divide(10, remainder);
backwards.push_back(unsigned(remainder)+'0');
}while(value);
std::copy(backwards.rbegin(), backwards.rend(), std::ostream_iterator(out));
return out;
}
丸めがオプションである場合、ほとんどのbignumも同様に変換するのはかなり簡単なはずです。これは非常に高速double
です。
つまり、64 個の最上位ビットを にコピーし、それを に変換してから、2.0 を有効ビット数から 64 を引いた数で乗じます (先頭のゼロをスキップする必要があるため、有効ビットと呼びます)。150 の有効ビットがあり、上位 64 を にコピーし、それを に変換し、それに~ 7.73e+25 を掛けて結果を取得します。有効ビットが 40 ビットしかない場合でも、右側にゼロを埋め込んでも機能します。40 ビットを の MSB にコピーし、それを に変換し、それに~ 5.96e-8 を掛けて結果を取得します。unsigned long
double
unsigned long
double
std::pow(2.0, 150-64)
unsigned long
double
std::pow(2.0, 40-64)
編集
Oli Charlesworth がDouble Dabbleのウィキペディア ページへのリンクを投稿しました。ばかげていると思いませんか。