问题
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