打印非常长的二进制表示的整数值

时间:2013-01-04 20:16:09

标签: c++ visual-c++ c++11

假设你有一个很长的二进制字(> 64bit),它代表一个无符号整数值,你想打印实际的数字。我们正在谈论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 显然有一个浮点指数,这没有任何帮助。

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

您诚挚的,
阿明

1 个答案:

答案 0 :(得分: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也应该是相当简单的,这将是 LOT 更快。即,将64个最高有效位复制到unsigned long,将其转换为double,然后乘以2.0,得到有效位数减去64的幂。(我说有效位,因为你必须跳过任何前导零)
因此,如果您有150个有效位,请将前64位复制为unsigned long,将其转换为double,然后将其乘以std::pow(2.0, 150-64) ~7.73e + 25以获得结果。如果你只有40个有效位,在右边填充零,它仍然有效。将40位复制到unsigned long的MSB,将其转换为double,然后乘以std::pow(2.0, 40-64) ~5.96e-8得到结果!

修改

Oli Charlesworth在Double Dabble上发布了维基百科页面的链接,该链接打破了我在水中展示的第一个算法。我不觉得傻。