Math 如何计算大数的模?

Math 如何计算大数的模?,math,modulo,Math,Modulo,如何不用计算器计算5^55模数221的模数 我想在密码学的数论中有一些简单的原理来计算这些东西。好的,那么你要计算a^b mod m。首先,我们将采用一种简单的方法,然后看看如何改进它 首先,减少模m。这意味着,找到一个数字a1,这样0就可以作为初始点,即221=13*17。因此,将其分解为两部分,最后将其组合在一起,一部分用于mod 13,另一部分用于mod 17。第二,我相信有一些证据证明a^(p-1)=1 mod p适用于所有非零a,这也有助于减少您的问题,因为对于mod 13的情况,当1

如何不用计算器计算5^55模数221的模数


我想在密码学的数论中有一些简单的原理来计算这些东西。

好的,那么你要计算
a^b mod m
。首先,我们将采用一种简单的方法,然后看看如何改进它

首先,减少模m。这意味着,找到一个数字
a1
,这样
0就可以作为初始点,即221=13*17。因此,将其分解为两部分,最后将其组合在一起,一部分用于mod 13,另一部分用于mod 17。第二,我相信有一些证据证明a^(p-1)=1 mod p适用于所有非零a,这也有助于减少您的问题,因为对于mod 13的情况,当13*4=52时,5^55变为5^3。如果你研究“有限域”这个主题,你可能会发现一些关于如何解决这个问题的好结果


编辑:我提到因子的原因是,这创建了一种将零因子分解为非零元素的方法,就好像你尝试了13^2*17^4 mod 221,答案是零,因为13*17=221。很多大数不会是素数,尽管有很多方法可以找到大素数,因为它们在密码学和数学中的其他领域中被大量使用。

你要找的是模幂运算,特别是模二进制幂运算。这有伪代码。

要添加到Jason的答案中:

您可以使用指数的二进制展开来加速该过程(这可能对非常大的指数很有帮助)。首先计算5,5^2,5^4,5^8 mod 221-通过重复平方运算:

 5^1 = 5(mod 221)
 5^2 = 5^2 (mod 221) = 25(mod 221)
 5^4 = (5^2)^2 = 25^2(mod 221) = 625 (mod 221) = 183(mod221)
 5^8 = (5^4)^2 = 183^2(mod 221) = 33489 (mod 221) = 118(mod 221)
5^16 = (5^8)^2 = 118^2(mod 221) = 13924 (mod 221) = 1(mod 221)
5^32 = (5^16)^2 = 1^2(mod 221) = 1(mod 221)
现在我们可以写作了

55 = 1 + 2 + 4 + 16 + 32

so 5^55 = 5^1 * 5^2 * 5^4 * 5^16 * 5^32 
        = 5   * 25  * 625 * 1    * 1 (mod 221)
        = 125 * 625 (mod 221)
        = 125 * 183 (mod 183) - because 625 = 183 (mod 221)
        = 22875 ( mod 221)
        = 112 (mod 221)

您可以看到,对于非常大的指数,这将快得多(我相信这是对数,而不是b中的线性,但不确定。)

这是我为IBAN验证编写的代码的一部分。请随意使用

    static void Main(string[] args)
    {
        int modulo = 97;
        string input = Reverse("100020778788920323232343433");
        int result = 0;
        int lastRowValue = 1;

        for (int i = 0; i < input.Length; i++)
        {
            // Calculating the modulus of a large number Wikipedia http://en.wikipedia.org/wiki/International_Bank_Account_Number                                                                        
            if (i > 0)
            {
                lastRowValue = ModuloByDigits(lastRowValue, modulo);
            }
            result += lastRowValue * int.Parse(input[i].ToString());
        }
        result = result % modulo;
        Console.WriteLine(string.Format("Result: {0}", result));            
    }

    public static int ModuloByDigits(int previousValue, int modulo)
    {
        // Calculating the modulus of a large number Wikipedia http://en.wikipedia.org/wiki/International_Bank_Account_Number                        
        return ((previousValue * 10) % modulo);
    }
    public static string Reverse(string input)
    {
        char[] arr = input.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
static void Main(字符串[]args)
{
整数模=97;
字符串输入=反向(“1000207788892032323434333”);
int结果=0;
int lastRowValue=1;
for(int i=0;i0)
{
lastRowValue=ModuleByDigits(lastRowValue,模);
}
结果+=lastRowValue*int.Parse(输入[i].ToString());
}
结果=结果%模;
WriteLine(string.Format(“Result:{0}”,Result));
}
公共静态int-moduleByDigits(int-previousValue,int-module)
{
//计算大量维基百科的模数http://en.wikipedia.org/wiki/International_Bank_Account_Number                        
返回((以前的值*10)%modulo);
}
公共静态字符串反转(字符串输入)
{
char[]arr=input.ToCharArray();
阵列。反向(arr);
返回新字符串(arr);
}
/*该算法来自《离散数学及其应用》一书
应用程序第五版“由肯尼思H.罗森。
(基本^exp)%mod
*/
整数模(整数基、无符号整数表达式、无符号整数模)
{
int x=1;
int power=基准%mod;
对于(int i=0;i>i);
if(最小信号位)
x=(x*功率)%mod;
功率=(功率*功率)%mod;
}
返回x;
}

只需提供Jason答案的另一个C实现

在与同学讨论后,根据Jason的解释,如果您不太关心性能,我更喜欢递归版本:

例如:

#include<stdio.h>

int mypow( int base, int pow, int mod ){
    if( pow == 0 ) return 1;
    if( pow % 2 == 0 ){
        int tmp = mypow( base, pow >> 1, mod );
        return tmp * tmp % mod;
    }
    else{
        return base * mypow( base, pow - 1, mod ) % mod;
    }
}

int main(){
    printf("%d", mypow(5,55,221));
    return 0;
}
#包括
int-mypow(int-base,int-pow,int-mod){
如果(pow==0)返回1;
如果(功率%2==0){
int tmp=mypow(基本,pow>>1,mod);
返回tmp*tmp%mod;
}
否则{
返回基地*mypow(基地,pow-1,mod)%mod;
}
}
int main(){
printf(“%d”,mypow(5,55221));
返回0;
}
Jason用Java给出的答案(注意
i

private static void testmodules(){
int bse=5,exp=55,mod=221;
int a1=bse%mod;
int p=1;
系统输出打印项次(“1.”+(p%mod)+“*”+bse+”=“+(p%mod)*bse+“mod”+mod);
对于(int i=1;i
这称为模幂运算()

假设您有以下表达式:

19 ^ 3 mod 7
您可以执行以下操作,而不是直接为19通电:

(((19 mod 7) * 19) mod 7) * 19) mod 7
但这也需要很长的时间,因为有很多连续的乘法,所以你可以在平方值上进行乘法:

x mod N -> x ^ 2 mod N -> x ^ 4 mod -> ... x ^ 2 |log y| mod N
模幂算法假设:

x ^ y == (x ^ |y/2|) ^ 2 if y is even
x ^ y == x * ((x ^ |y/2|) ^ 2) if y is odd
因此,递归模幂算法在java中看起来是这样的:

/**
* Modular exponentiation algorithm
* @param x Assumption: x >= 0
* @param y Assumption: y >= 0
* @param N Assumption: N > 0
* @return x ^ y mod N
*/
public static long modExp(long x, long y, long N) {
    if(y == 0)
        return 1 % N;

    long z = modExp(x, Math.abs(y/2), N);

    if(y % 2 == 0)
        return (long) ((Math.pow(z, 2)) % N);
    return (long) ((x * Math.pow(z, 2)) % N);
}

特别感谢您在比较y和0时发现返回值不正确的错误

这里有一个解释:devx链接没有多大用处,在数论中还有其他简单的方法可以解决这类问题,好吧。@Priyank Bolia:别担心,这个问题不太可能解决。这是个好问题。如果它被关闭,将会有很多人投票重新开放。是的,我们很多人都知道,有时计算机科学涉及数学。@JB King:MathOverflow是指研究生及更高级别的数学;这个问题在那里是不受欢迎的。大多数编程语言都有一个内置的操作符。例如,在C派生语言中,
%
运算符是模运算符。因此,
int p=625%221
183
分配给
p
。通过将
625
除以
221
作为整数除数i,可以实现相同的功能
#include<stdio.h>

int mypow( int base, int pow, int mod ){
    if( pow == 0 ) return 1;
    if( pow % 2 == 0 ){
        int tmp = mypow( base, pow >> 1, mod );
        return tmp * tmp % mod;
    }
    else{
        return base * mypow( base, pow - 1, mod ) % mod;
    }
}

int main(){
    printf("%d", mypow(5,55,221));
    return 0;
}
private static void testModulus() {
    int bse = 5, exp = 55, mod = 221;

    int a1 = bse % mod;
    int p = 1;

    System.out.println("1. " + (p % mod) + " * " + bse + " = " + (p % mod) * bse + " mod " + mod);

    for (int i = 1; i < exp; i++) {
        p *= a1;
        System.out.println((i + 1) + ". " + (p % mod) + " * " + bse + " = " + ((p % mod) * bse) % mod + " mod " + mod);
        p = (p % mod);
    }

}
19 ^ 3 mod 7
(((19 mod 7) * 19) mod 7) * 19) mod 7
x mod N -> x ^ 2 mod N -> x ^ 4 mod -> ... x ^ 2 |log y| mod N
x ^ y == (x ^ |y/2|) ^ 2 if y is even
x ^ y == x * ((x ^ |y/2|) ^ 2) if y is odd
/**
* Modular exponentiation algorithm
* @param x Assumption: x >= 0
* @param y Assumption: y >= 0
* @param N Assumption: N > 0
* @return x ^ y mod N
*/
public static long modExp(long x, long y, long N) {
    if(y == 0)
        return 1 % N;

    long z = modExp(x, Math.abs(y/2), N);

    if(y % 2 == 0)
        return (long) ((Math.pow(z, 2)) % N);
    return (long) ((x * Math.pow(z, 2)) % N);
}