我将假设您已经有某种 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;
}
如果舍入是一种选择,那么将大多数 bignums 转换double
为也应该是相当简单的,这会快很多。即,将 64 个最高有效位复制unsigned long
到 a ,将其转换为 a double
,然后乘以 2.0 的有效位数减去 64 的幂。(我说有效位,因为您必须跳过任何前导零)
所以如果您有 150 个有效位,将前 64 位复制到 a 中unsigned long
,将其转换为 a double
,然后将其乘以std::pow(2.0, 150-64)
~ 7.73e+25 以获得结果。如果你只有 40 个有效位,在右边用零填充它仍然有效。将 40 位复制到 a 的 MSB unsigned long
,将其转换为 a double
,然后将其乘以std::pow(2.0, 40-64)
~ 5.96e-8 得到结果!
编辑
Oli Charlesworth 在Double Dabble上发布了一个指向维基百科页面的链接,这将我展示的第一个算法从水中吹了出来。我不觉得很傻吗。