繁体   English   中英

模除法返回负数

[英]Modulo division returning negative number

我正在C程序中执行以下模除法运算:

(5 ^ 6)mod 23 = 8

(5 ^ 15)mod 23 = 19

为了方便起见,我使用以下功能:

int mod_func(int p, int g, int x) {
    return ((int)pow((double)g, (double)x)) % p;
}

但是调用该函数时的操作结果不正确:

mod_func(23, 5, 6) //returns 8
mod_func(23, 5, 15) //returns -6

模运算符是否对操作数的大小有一定限制?

的整数部分pow(5, 15)不处于表示的int (假设的宽度int是32位)。 转换(在double转换表达式中从doubleint )是C和C ++中未定义的行为。

为避免未定义的行为,应使用fmod函数执行浮点余数运算。

5的幂15是30,517,578,125

您可以在int存储的最大值是2,147,483,647

您可以使用64位整数,但要注意,最终从double转换时会出现精度问题。

从内存来看,数论中有一条关于您正在执行的计算的规则,这意味着您无需计算整个功率扩展即可确定模结果。 但是我可能是错的。 自从我学到这些东西以来已经有很多年了。

啊,这是: 模幂

阅读该内容,并停止使用doublepow =)

int mod_func(int p, int g, int x)
{
    int r = g;
    for( int i = 1; i < x; i++ ) {
        r = (r * g) % p;
    }
    return r;
}

我的猜测是问题是5 ^ 15 = 30517578125,它大于INT_MAX (2147483647)。 您当前正在将其强制转换为int ,这是失败的。

如前所述,您的第一个问题

int mod_func(int p, int g, int x) {
    return ((int)pow((double)g, (double)x)) % p;
}

pow(g,x)通常超出int范围,然后您将其结果转换为int行为未定义,并且无论所得int是什么,都没有理由相信它与所需的模数有关。

下一个问题是pow(g,x)double可能不准确。 除非g为2的幂,否则即使在一定范围内,数学结果也无法精确表示为足够大的指数的double ,但是如果数学结果可精确表示(取决于pow的实现),也可能会发生。

如果您进行数论计算-并且以整数为模计算幂的余数为1-您应该仅使用整数类型。

对于手头的情况,可以通过重复平方来使用幂运算,计算所有中间结果的残差。 如果模数p足够小以至于(p-1)*(p-1)不会溢出,

int mod_func(int p, int g, int x) {
    int aux = 1;
    g %= p;
    while(x > 0) {
        if (x % 2 == 1) {
            aux = (aux * g) % p;
        }
        g = (g * g) % p;
        x /= 2;
    }
    return aux;
}

可以。 如果p可以更大,则需要使用更大的类型进行计算。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM