我正在尝试创建一个快速计算x ^ y mod z的函数。它在计算像2 ^ 63 mod 3这样的东西时效果很好,但在2 ^ 64 mod 3和更高的指数时它只返回0.
我怀疑某处有溢出,但我无法将其固定下来。我已经在计算(*和mod)的地方尝试了显式的强制转换,我还创建了我的存储变量(%ROWTYPE
,resPow
)curPow
(建议{{3} })但这并没有多大帮助。
unsigned long long int
答案 0 :(得分:1)
我怀疑某处有溢出,
是的,curPow * curPow
和resPow * curPow
都可能在数学上溢出。
这里包含溢出的通常方法是在中间产品上执行 mod 。
// curPow = curPow * curPow;
curPow = (curPow * curPow) % nMod;
// resPow =resPow * curPow;
resPow = (resPow * curPow) % nMod;
nMod < ULLONG_MAX/(nMod - 1)
时就足够了。 (mod值是unsigned long long
)精度的一半。否则需要采取更极端的措施,如:Modular exponentiation without range restriction。
次要的东西
for(int i = 0; i < 32; i++)
假设lint/unsigned long
为32位。便携式代码可以避免幻数。 unsigned long
在各种平台上都是64位。
LL
。 U
对于安静各种编译器警告仍然很有用。
// unsigned long long int resPow = 1ULL;
unsigned long long int resPow = 1U;