Рубрики

Как избежать переполнения при модульном умножении?

Ниже рассмотрим простой способ умножения двух чисел.

// Простое решение, которое вызывает переполнение при
// значение (% mod) * (b% mod) становится больше чем
// максимальное значение long long int
#define ll long long

  
ll multiply(ll a, ll b, ll mod)
{

   return ((a % mod) * (b % mod)) % mod;

}

Вышеуказанная функция работает нормально, когда умножение не приводит к переполнению. Но если входные числа таковы, что результат умножения больше максимального предела.

Например, приведенный выше метод завершается ошибкой, когда mod = 10 11 , a = 9223372036854775807 ( самый большой long long int ) и b = 9223372036854775807 ( самый большой long long int ). Обратите внимание, что могут быть меньшие значения, для которых может произойти сбой. Может быть еще много примеров меньших значений. Фактически любой набор значений, для которого умножение может привести к значению, превышающему максимальный предел.

Как избежать переполнения?
Мы можем умножить рекурсивно, чтобы преодолеть сложность переполнения. Чтобы умножить a * b, сначала вычислите a * b / 2, а затем добавьте его дважды. Для вычисления a * b / 2 вычислите a * b / 4 и т. Д. (Аналогично алгоритму возведения в степень n ).

// To compute (a * b) % mod
multiply(a,  b, mod)
1)  ll res = 0; // Initialize result
2)  a = a % mod.
3)  While (b > 0)
        a) If b is odd, then add 'a' to result.
               res = (res + a) % mod
        b) Multiply 'a' with 2
           a = (a * 2) % mod
        c) Divide 'b' by 2
           b = b/2  
4)  Return res 

Ниже приведена реализация.

C ++

// C ++ программа для модульного умножения без
// любое переполнение
#include<iostream>

using namespace std;

  

typedef long long int ll;

  
// Для вычисления (a * b)% mod
ll mulmod(ll a, ll b, ll mod)
{

    ll res = 0; // Инициализировать результат

    a = a % mod;

    while (b > 0)

    {

        // Если b нечетно, добавить 'a' к результату

        if (b % 2 == 1)

            res = (res + a) % mod;

  

        // Умножаем 'a' на 2

        a = (a * 2) % mod;

  

        // Делим b на 2

        b /= 2;

    }

  

    // Возвращаем результат

    return res % mod;

}

  
// Драйвер программы

int main()

{

   ll a = 9223372036854775807, b = 9223372036854775807;

   cout << mulmod(a, b, 100000000000);

   return 0;

}

Джава

// Java-программа для модульного умножения
// без переполнения

  

class GFG 

{

  

    // Для вычисления (a * b)% mod

    static long mulmod(long a, long b, 

                            long mod) 

    {

        long res = 0; // Инициализировать результат

        a = a % mod;

        while (b > 0)

        {

            // Если b нечетно, добавить 'a' к результату

            if (b % 2 == 1

            {

                res = (res + a) % mod;

            }

  

            // Умножаем 'a' на 2

            a = (a * 2) % mod;

  

            // Делим b на 2

            b /= 2;

        }

  

        // Возвращаем результат

        return res % mod;

    }

  

    // Код драйвера

    public static void main(String[] args)

    {

  

        long a = 9223372036854775807L, b = 9223372036854775807L;

        System.out.println(mulmod(a, b, 100000000000L));

    }

  
// Этот код предоставлен Rajput-JI

python3

# Python3 программа для модульного умножения
# без переполнения

  
# Для вычисления (a * b)% mod

def mulmod(a, b, mod):

  

    res = 0; # Инициализировать результат

    a = a % mod;

    while (b > 0):

      

        # Если b нечетно, добавьте «a» к результату

        if (b % 2 == 1):

            res = (res + a) % mod;

  

        # Умножьте «а» на 2

        a = (a * 2) % mod;

  

        # Разделить b на 2

        b //= 2;

  

    # Вернуть результат

    return res % mod;

  
Код водителя

a = 9223372036854775807;

b = 9223372036854775807;

print(mulmod(a, b, 100000000000));

  
# Этот код предоставлен mits

C #

// C # программа для модульного умножения
// без переполнения

using System;

  

class GFG 

  
// Для вычисления (a * b)% mod

static long mulmod(long a, long b, long mod) 

    long res = 0; // Инициализировать результат

    a = a % mod; 

    while (b > 0) 

    

        // Если b нечетно, добавить 'a' к результату

        if (b % 2 == 1) 

        

            res = (res + a) % mod; 

        

  

        // Умножаем 'a' на 2

        a = (a * 2) % mod; 

  

        // Делим b на 2

        b /= 2; 

    

  

    // Возвращаем результат

    return res % mod; 

  
// Код драйвера

public static void Main(String[] args) 

    long a = 9223372036854775807L, 

         b = 9223372036854775807L; 

    Console.WriteLine(mulmod(a, b, 100000000000L)); 


  
// Этот код предоставлен 29AjayKumar

Выход:

84232501249

Спасибо Уткаршу Триведи за предложенное решение.

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Как избежать переполнения при модульном умножении?

0.00 (0%) 0 votes