-1

假设您有一个很长的二进制字(>64 位),它表示一个无符号整数值,并且您想打印实际数字。我们说的是 C++,所以假设您从bool[ ]std::vector<bool>std::bitset开始,并以std::string或某种std::ostream结束-无论您喜欢什么解决方案。但请只使用核心语言和 STL。

现在,我怀疑,您必须逐块评估它,以获得一些中间结果,这些结果足够小以存储 - 最好以 10 为底,如 x·10 k。我可以想办法从那一刻开始收集这个数字。但由于没有对应以 10 为底的块宽度,我不知道该怎么做。当然,你可以从任何其他块宽度开始,比如 3,得到 x·(2 3 ) k形式的中间体,然后将其转换为以 10 为底,但这会导致 x·10 3· k·lg2显然有一个浮点指数,这没有任何帮助。

无论如何,我已经厌倦了这种数学废话,我会很感激一个深思熟虑的建议。

此致,
阿明

4

1 回答 1

1

我将假设您已经有某种 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上发布了一个指向维基百科页面的链接,这将我展示的第一个算法从水中吹了出来。我不觉得很傻吗。

于 2013-01-04T20:46:18.753 回答