计算pow时无符号Long Int溢出

时间:2018-05-10 13:15:16

标签: c multiplication exponential unsigned-long-long-int

我正在尝试创建一个快速计算x ^ y mod z的函数。它在计算像2 ^ 63 mod 3这样的东西时效果很好,但在2 ^ 64 mod 3和更高的指数时它只返回0.

我怀疑某处有溢出,但我无法将其固定下来。我已经在计算(*和mod)的地方尝试了显式的强制转换,我还创建了我的存储变量(%ROWTYPEresPowcurPow(建议{{3} })但这并没有多大帮助。

unsigned long long int

1 个答案:

答案 0 :(得分:1)

  

我怀疑某处有溢出,

是的,curPow * curPowresPow * 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位。

此处不需要

LLU对于安静各种编译器警告仍然很有用。

// unsigned long long int resPow = 1ULL;
unsigned long long int resPow = 1U;