Shifting big numbers

こ雲淡風輕ζ 提交于 2019-12-11 11:29:10

问题


X = 712360810625491574981234007851998 is represented using a linked list and each node is an unsigned int

Is there a fast way to do X << 8 X << 591 other than X * 2^8 X * 2^591 ?


回答1:


Bit shifting is very easy in any arbitrary number of bits. Just remember to shift the overflowed bits to the next element. That's all

Below is a left shift by 3 example

uint64_t i1, i2, i3, o1, o2, o3; // {o3, o2, o1} = {i3, i2, i1} << 3;

o3 = i3 << 3 | i2 >> (32 - 3);
o2 = i2 << 3 | i1 >> (32 - 3);
o1 = i1 << 3;

Similar for shifting right, just iterate in the reverse direction.

Edit:

It seems that you're using base 109 for your large number, so binary shifting does not apply here. "Shifting" left/right N digits in a base B is equivalent to multiplying the number by BN and B-N respectively. You can't do binary shift in decimal and vice versa

If you don't change your base then you have only one solution, that's multiplying the number by 2591. If you want to shift like in binary you must change to a base that is a power of 2 like base 232 or base 264

A general solution would be like this, with the limbs stored in little-endian and each digit is in base 2CHAR_BIT*sizeof(T)

template<typename T>
void rshift(std::vector<T>& x, std::size_t shf_amount) // x >>= shf_amount
{
    constexpr std::size_t width = CHAR_BIT*sizeof(T);
    if (shf_amount > width)
        throw;

    const std::size_t shift     = shf_amount % width;
    const std::size_t limbshift = shf_amount / width;

    std::size_t i = 0;
    for (; i < x.size() - limbshift - 1; ++i)
        x[i] = (x[i + limbshift] >> shift) | (x[i + 1 + limbshift] << (width - shift));
    x[i++] = x[i + limbshift] >> shift;
    for (; i < x.size() ; ++i)
        x[i] = 0;
}

Moreover from the tag you're likely using a linked-list for storing the limbs which is not cache-friendly due to elements scattering all around the memory space, and it also wastes a lot of memory due to the next pointers. In fact you shouldn't use linked list in most real life problems

  • Bjarne Stroustrup says we must avoid linked lists
  • Why you should never, ever, EVER use linked-list in your code again
  • Number crunching: Why you should never, ever, EVER use linked-list in your code again
  • Bjarne Stroustrup: Why you should avoid Linked Lists
  • Are lists evil?—Bjarne Stroustrup



回答2:


I think, if you use 64 bit integer the code should be

    o3 = i3 << 3 | i2 >> (32 - 3);
    .....


来源:https://stackoverflow.com/questions/10526840/shifting-big-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!