基于GMP库的mpz_class变量二进制末尾n位获取方法问询
最优方法:用GMP的按位与或取模操作(避免字符串转换)
嘿,我明白你的困扰——用get_str转二进制字符串确实对大数太不友好了,而直接用移位运算符又行不通。其实GMP提供了很高效的mpz级函数来解决这个问题,完全没必要用到复杂的mpn底层函数。
为什么你的代码编译失败?
首先说下你尝试的移位代码问题:mpz_class并没有重载operator<<来接受另一个mpz_class作为右操作数(你写的mpz_class(1) << a里,a是mpz_class类型)。如果要对大数做左移,得用GMP提供的mpz_mul_2exp函数(本质是乘以2的指定次幂),比如你要计算1 << 5,可以这么写:
mpz_class base(1); mpz_class shifted; mpz_mul_2exp(shifted.get_mpz_t(), base.get_mpz_t(), 5); // 结果是32
获取二进制最后n位的最优方案
取二进制最后n位,本质就是和掩码(2^n - 1)做按位与,或者对2^n取模(因为2的幂次情况下,这两个操作结果完全等价)。这两种方法都是GMP底层实现的高效整数运算,没有字符串转换的开销。
方法1:按位与(推荐)
先生成掩码2^n -1,再和原数做按位与:
#include <iostream> #include <gmpxx.h> using namespace std; int main() { mpz_class big_num("123456789012345678901234567890"); // 任意大数 unsigned int n = 15; // 要取最后15位二进制 // 生成掩码:2^n - 1 mpz_class mask; mpz_ui_pow_ui(mask.get_mpz_t(), 2, n); // 先计算2^n mask -= 1; // 得到2^n -1 // 取最后n位:原数 & 掩码 mpz_class last_n_bits; mpz_and(last_n_bits.get_mpz_t(), big_num.get_mpz_t(), mask.get_mpz_t()); // 输出结果 cout << "原数: " << big_num << endl; cout << "二进制最后" << n << "位的十进制值: " << last_n_bits << endl; cout << "二进制形式: " << last_n_bits.get_str(2) << endl; return 0; }
方法2:取模运算
因为最后n位的数值等于原数对2^n取模,也能达到同样效果:
// 省略前面的变量定义... mpz_class mod_value; mpz_ui_pow_ui(mod_value.get_mpz_t(), 2, n); // 计算2^n mpz_mod(last_n_bits.get_mpz_t(), big_num.get_mpz_t(), mod_value.get_mpz_t());
为什么不用mpn_lshift?
你提到的mpn_lshift是GMP最底层的函数,操作的是大数的原始 limb 数组(比如把数组里的每个元素移位),对于取最后n位这个简单任务来说完全是杀鸡用牛刀——mpz级别的mpz_and/mpz_mod已经足够高效,而且代码可读性强得多。
内容的提问来源于stack exchange,提问作者northerner
相关产品推荐
相关产品推荐

