80

How to calculate modulus of 5^55 modulus 221 without much use of calculator?

I guess there are some simple principles in number theory in cryptography to calculate such things.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
Priyank Bolia
  • 14,077
  • 14
  • 61
  • 82
  • 1
    Here is an explanation: http://www.devx.com/tips/Tip/39012 – tur1ng Feb 01 '10 at 15:36
  • the devx link is not of much use, there are other simple methods in number theory for such things, AFAIK. – Priyank Bolia Feb 01 '10 at 15:42
  • close for what, have you ever read cryptography? – Priyank Bolia Feb 01 '10 at 15:50
  • 1
    @Priyank Bolia: Don't worry, it's unlikely this question will be closed. It's a good question. If it is closed, there will be plenty of people voting to reopen. – jason Feb 01 '10 at 16:19
  • 4
    Yeah, many of us are aware that sometimes computer science involves mathematics. – Cascabel Feb 01 '10 at 16:33
  • Math Overflow would be another place to post this kind of question: http://mathoverflow.net/ – JB King Feb 01 '10 at 16:49
  • 14
    @JB King: MathOverflow is for mathematics at the graduate-level and higher; this question would be frowned upon there. – jason Feb 01 '10 at 17:00
  • Related: [https://www.quora.com/Whats-an-efficient-algorithm-to-convert-the-base-of-a-BIG-number](https://www.quora.com/Whats-an-efficient-algorithm-to-convert-the-base-of-a-BIG-number) – Pacerier Mar 22 '17 at 07:14

10 Answers10

105

Okay, so you want to calculate a^b mod m. First we'll take a naive approach and then see how we can refine it.

First, reduce a mod m. That means, find a number a1 so that 0 <= a1 < m and a = a1 mod m. Then repeatedly in a loop multiply by a1 and reduce again mod m. Thus, in pseudocode:

a1 = a reduced mod m
p = 1
for(int i = 1; i <= b; i++) {
    p *= a1
    p = p reduced mod m
}

By doing this, we avoid numbers larger than m^2. This is the key. The reason we avoid numbers larger than m^2 is because at every step 0 <= p < m and 0 <= a1 < m.

As an example, let's compute 5^55 mod 221. First, 5 is already reduced mod 221.

  1. 1 * 5 = 5 mod 221
  2. 5 * 5 = 25 mod 221
  3. 25 * 5 = 125 mod 221
  4. 125 * 5 = 183 mod 221
  5. 183 * 5 = 31 mod 221
  6. 31 * 5 = 155 mod 221
  7. 155 * 5 = 112 mod 221
  8. 112 * 5 = 118 mod 221
  9. 118 * 5 = 148 mod 221
  10. 148 * 5 = 77 mod 221
  11. 77 * 5 = 164 mod 221
  12. 164 * 5 = 157 mod 221
  13. 157 * 5 = 122 mod 221
  14. 122 * 5 = 168 mod 221
  15. 168 * 5 = 177 mod 221
  16. 177 * 5 = 1 mod 221
  17. 1 * 5 = 5 mod 221
  18. 5 * 5 = 25 mod 221
  19. 25 * 5 = 125 mod 221
  20. 125 * 5 = 183 mod 221
  21. 183 * 5 = 31 mod 221
  22. 31 * 5 = 155 mod 221
  23. 155 * 5 = 112 mod 221
  24. 112 * 5 = 118 mod 221
  25. 118 * 5 = 148 mod 221
  26. 148 * 5 = 77 mod 221
  27. 77 * 5 = 164 mod 221
  28. 164 * 5 = 157 mod 221
  29. 157 * 5 = 122 mod 221
  30. 122 * 5 = 168 mod 221
  31. 168 * 5 = 177 mod 221
  32. 177 * 5 = 1 mod 221
  33. 1 * 5 = 5 mod 221
  34. 5 * 5 = 25 mod 221
  35. 25 * 5 = 125 mod 221
  36. 125 * 5 = 183 mod 221
  37. 183 * 5 = 31 mod 221
  38. 31 * 5 = 155 mod 221
  39. 155 * 5 = 112 mod 221
  40. 112 * 5 = 118 mod 221
  41. 118 * 5 = 148 mod 221
  42. 148 * 5 = 77 mod 221
  43. 77 * 5 = 164 mod 221
  44. 164 * 5 = 157 mod 221
  45. 157 * 5 = 122 mod 221
  46. 122 * 5 = 168 mod 221
  47. 168 * 5 = 177 mod 221
  48. 177 * 5 = 1 mod 221
  49. 1 * 5 = 5 mod 221
  50. 5 * 5 = 25 mod 221
  51. 25 * 5 = 125 mod 221
  52. 125 * 5 = 183 mod 221
  53. 183 * 5 = 31 mod 221
  54. 31 * 5 = 155 mod 221
  55. 155 * 5 = 112 mod 221

Therefore, 5^55 = 112 mod 221.

Now, we can improve this by using exponentiation by squaring; this is the famous trick wherein we reduce exponentiation to requiring only log b multiplications instead of b. Note that with the algorithm that I described above, the exponentiation by squaring improvement, you end up with the right-to-left binary method.

a1 = a reduced mod m
p = 1
while (b > 0) {
     if (b is odd) {
         p *= a1
         p = p reduced mod m
     }
     b /= 2
     a1 = (a1 * a1) reduced mod m
}

Thus, since 55 = 110111 in binary

  1. 1 * (5^1 mod 221) = 5 mod 221
  2. 5 * (5^2 mod 221) = 125 mod 221
  3. 125 * (5^4 mod 221) = 112 mod 221
  4. 112 * (5^16 mod 221) = 112 mod 221
  5. 112 * (5^32 mod 221) = 112 mod 221

Therefore the answer is 5^55 = 112 mod 221. The reason this works is because

55 = 1 + 2 + 4 + 16 + 32

so that

5^55 = 5^(1 + 2 + 4 + 16 + 32) mod 221
     = 5^1 * 5^2 * 5^4 * 5^16 * 5^32 mod 221
     = 5 * 25 * 183 * 1 * 1 mod 221
     = 22875 mod 221
     = 112 mod 221

In the step where we calculate 5^1 mod 221, 5^2 mod 221, etc. we note that 5^(2^k) = 5^(2^(k-1)) * 5^(2^(k-1)) because 2^k = 2^(k-1) + 2^(k-1) so that we can first compute 5^1 and reduce mod 221, then square this and reduce mod 221 to obtain 5^2 mod 221, etc.

The above algorithm formalizes this idea.

Pacerier
  • 86,231
  • 106
  • 366
  • 634
jason
  • 236,483
  • 35
  • 423
  • 525
  • 1
    Well, most programming languages have a built-in operator for this. For example, in C-derived languages, the `%` operator is the modulus operator. Thus, `int p = 625 % 221` would assign `183` to `p`. You can achieve the same functionality by dividing `625` by `221` as integer division and getting the answer `2`. Then you take `625 - 2 * 221` to get the remainder. In this case `625 - 2 * 221 = 183` which is the answer. – jason Feb 01 '10 at 15:48
  • this takes too much multiplication 54 times, is there even faster method. – Priyank Bolia Feb 01 '10 at 15:49
  • 2
    Yes, as I described in the paragraph at the end you do exponentiation by squaring. – jason Feb 01 '10 at 15:52
  • 6
    You can actually do much better than exponentiation by squaring, especially in the large-exponent case. Notice that you found that `5^16 == 1 (mod 221)`. Therefore, `5^k == 5^(k%16) (mod 221)`. – Cascabel Feb 01 '10 at 16:01
  • @Jefromi, is there an easy way to find the period of a^b mod c? By easy of course, I mean sublogarithmic. – JSchlather Feb 01 '10 at 16:28
  • If you only need the order of one such $a$, there's no way besides iteration. However, with large enough exponents, it's still going to be worth it (on average), or with repeated calculations. I believe if you wanted the orders of *all* $a$, you could work something out though... – Cascabel Feb 01 '10 at 16:32
  • 2
    @Jason: you have written: *First, reduce a mod m. That means, find a number a1 so that 0 <= a1 < m and a = a1 mod m.* It looks like the last equation contains a typo, shouldn't it be *a1 = a mod m* instead? – Timofey Apr 10 '11 at 02:38
  • @Jason: why do you use *a reduced mod m*? It looks like *a mod m* perfectly explains what do you want to do, doesn't it? – Timofey Apr 10 '11 at 14:06
  • 2
    @Jason for the most part, if you just added ";" (and a few other characters) to your pseudocode, it would be C. – haneefmubarak Sep 02 '13 at 18:31
  • i'm maybe a bit braindead atm, but WHY can you apply the modulo function on each 'step' – pvgoddijn Jun 04 '18 at 13:21
30

To add to Jason's answer:

You can speed the process up (which might be helpful for very large exponents) using the binary expansion of the exponent. First calculate 5, 5^2, 5^4, 5^8 mod 221 - you do this by repeated squaring:

 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)

Now we can write

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)

You can see how for very large exponents this will be much faster (I believe it's log as opposed to linear in b, but not certain.)

Tom Smith
  • 1,659
  • 1
  • 15
  • 20
  • 7
    this is even better explanation – Priyank Bolia Feb 01 '10 at 15:56
  • 1
    I suspect that it's actually much faster (in general) to avoid the exponentiation by squaring, and instead search directly for the least exponent $k$ such that $5^k == 5 (mod 221)$. This does of course depend on size of exponent versus modulus, but once you have that exponent, you just need a single calculation (exponent mod k) and lookup. Note it's also therefore definitely better if you need to repeat similar calculations. (You can't in general look for $a^k == 1 (mod 221)$ since this only happens if $a$ and 221 are relatively prime) – Cascabel Feb 01 '10 at 16:06
  • 1
    well, no, in general finding the least exponent with that property is much slower than sqaure-and-multiply. But if you know the factorization of the modulus then you can easily compute the carmichael lambda function which is a mutliple of your k. – President James K. Polk Feb 02 '10 at 00:31
12
/* The algorithm is from the book "Discrete Mathematics and Its
   Applications 5th Edition" by Kenneth H. Rosen.
   (base^exp)%mod
*/

int modular(int base, unsigned int exp, unsigned int mod)
{
    int x = 1;
    int power = base % mod;

    for (int i = 0; i < sizeof(int) * 8; i++) {
        int least_sig_bit = 0x00000001 & (exp >> i);
        if (least_sig_bit)
            x = (x * power) % mod;
        power = (power * power) % mod;
    }

    return x;
}
Timothy Kwok
  • 301
  • 2
  • 9
3
5^55 mod221

= (   5^10         * 5^10         * 5^10         * 5^10          * 5^10          * 5^5) mod221    

= ( ( 5^10) mod221 * 5^10         * 5^10         * 5^10          * 5^10          * 5^5) mod221 

= (   77           * 5^10         * 5^10         * 5^10          * 5^10          * 5^5) mod221   

= ( ( 77           * 5^10) mod221 * 5^10         * 5^10          * 5^10          * 5^5) mod221 

= (   183                         * 5^10         * 5^10          * 5^10          * 5^5) mod221 

= ( ( 183                         * 5^10) mod221 * 5^10          * 5^10          * 5^5) mod221 

= (   168                                        * 5^10          * 5^10          * 5^5) mod221 

= ( ( 168                                        * 5^10) mod 221 * 5^10          * 5^5) mod221 

= (   118                                                        * 5^10          * 5^5) mod221 

= ( ( 118                                                        * 5^10) mod 221 * 5^5) mod221 

= (   25                                                                         * 5^5) mod221 

=     112
Pacerier
  • 86,231
  • 106
  • 366
  • 634
2

Chinese Remainder Theorem comes to mind as an initial point as 221 = 13 * 17. So, break this down into 2 parts that get combined in the end, one for mod 13 and one for mod 17. Second, I believe there is some proof of a^(p-1) = 1 mod p for all non zero a which also helps reduce your problem as 5^55 becomes 5^3 for the mod 13 case as 13*4=52. If you look under the subject of "Finite Fields" you may find some good results on how to solve this.

EDIT: The reason I mention the factors is that this creates a way to factor zero into non-zero elements as if you tried something like 13^2 * 17^4 mod 221, the answer is zero since 13*17=221. A lot of large numbers aren't going to be prime, though there are ways to find large primes as they are used a lot in cryptography and other areas within Mathematics.

JB King
  • 11,860
  • 4
  • 38
  • 49
  • well I don't know the factorials in the first place, and I am trying to prove that the number is a prime, using Miller Rabin Algorithm. So, I am at the opposite end. – Priyank Bolia Feb 01 '10 at 15:54
  • There aren't any factorials here, but there is a factorization which is different. The factorial of an integer n is defined as the product of all positive integers less than n,e.g. 2!=2, 3!=6, etc. and is often expressed using the ! symbol. Factorization is different and there isn't a common symbol used to express an integer being factored. – JB King Feb 01 '10 at 16:54
2

What you're looking for is modular exponentiation, specifically modular binary exponentiation. This wikipedia link has pseudocode.

job
  • 9,003
  • 7
  • 41
  • 50
2

This is part of code I made for IBAN validation. Feel free to use.

    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);
    }
2

Jason's answer in Java (note i < exp).

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);
    }

}
Martin Pfeffer
  • 12,471
  • 9
  • 59
  • 68
1

Just provide another implementation of Jason's answer by C.

After discussing with my classmates, based on Jason's explanation, I like the recursive version more if you don't care about the performance very much:

For example:

#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;
}
Boris
  • 109
  • 6
1

This is called modular exponentiation(https://en.wikipedia.org/wiki/Modular_exponentiation).

Let's assume you have the following expression:

19 ^ 3 mod 7

Instead of powering 19 directly you can do the following:

(((19 mod 7) * 19) mod 7) * 19) mod 7

But this can take also a long time due to a lot of sequential multipliations and so you can multiply on squared values:

x mod N -> x ^ 2 mod N -> x ^ 4 mod -> ... x ^ 2 |log y| mod N

Modular exponentiation algorithm makes assumptions that:

x ^ y == (x ^ |y/2|) ^ 2 if y is even
x ^ y == x * ((x ^ |y/2|) ^ 2) if y is odd

And so recursive modular exponentiation algorithm will look like this in 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);
}

Special thanks to @chux for found mistake with incorrect return value in case of y and 0 comparison.

Stepan Pogosyan
  • 562
  • 1
  • 7
  • 15