Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid overflow in modular multiplication?

I know that,

(a*b)%m = ((a%m)*(b%m))%m

But there is a possibility of overflow. For simplicity lets assume size of integer is 2 bits. If a = 2 (i.e. 102) and b = 2 (i.e. 102), m = 3 (i.e. 112), then a%m and b%m turn out to be 2 and after multiplication, answer is 4 (i.e. 100) which does not fit in integer size. Final answer will be 0 if 2-lsb's are considered from 4. But actual answer is 1.

What should I do to avoid this situation?

like image 384
Bhavesh Munot Avatar asked Feb 01 '15 05:02

Bhavesh Munot


People also ask

How can overflow be prevented?

One very good way to prevent integer overflows is to use int64_t to implement integers. In most case, 64-bits ints will not commit overflow, unlike their 32-bits counterparts. There is actually very few downsides in using int64_t instead of int32_t .

How do you know if a multiplication will cause an overflow?

We have to check whether the multiplied value will exceed the 64-bit integer or not. If we multiply 100, and 200, it will not exceed, if we multiply 10000000000 and -10000000000, it will overflow.

What is overflow multiplication?

Multiplication. For multiplication, overflow means that the result cannot be expressed in 32 bits (it can always be expressed in 64 bits, whether signed or unsigned). Checking for overflow is simple if you have access to the high-order 32 bits of the product.

What can we do to avoid overflow errors if we need to deal with large numbers in Java?

Use a Different Data Type. If we want to allow values larger than 2147483647 (or smaller than -2147483648), we can simply use the long data type or a BigInteger instead. Though variables of type long can also overflow, the minimum and maximum values are much larger and are probably sufficient in most situations.


2 Answers

If m-1 squared doesn't fit in your integer type, you need to perform long multiplication. For your two-bit example, that means breaking your two-bit numbers into pairs of one-bit numbers (a high bit and a low bit) and multiplying all four pairs (high by high, high by low, low by high, low by low) individually. You can then get the result mod m for each pair (noting the actual places they represent, i.e. fours, twos, or ones) and add the results mod m.

like image 140
R.. GitHub STOP HELPING ICE Avatar answered Sep 21 '22 02:09

R.. GitHub STOP HELPING ICE


many small processor C implementations can directly check the result of a math operation for overflow/underflow.

Another way is to use a receiving field that is twice the length of the underlying int size I.E. for an int size of 2, use a result field of 4 bytes. (perhaps by a long long int) or transfer both numbers to double fields and multiply them then convert back to int (however, some precision in the result (I.E. the least significant digit) may be inaccurate.

Another way is to use an appropriate function from the math.h library.

Another way is to use long multiplication using arrays: this was copied from http://www.cquestions.com/2010/08/multiplication-of-large-numbers-in-c.html

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#define MAX 10000

char * multiply(char [],char[]);
int main(){
    char a[MAX];
    char b[MAX];
    char *c;
    int la,lb;
    int i;
    printf("Enter the first number : ");
    scanf("%s",a);
    printf("Enter the second number : ");
    scanf("%s",b);
    printf("Multiplication of two numbers : ");
    c = multiply(a,b);
    printf("%s",c);
    return 0;
}

char * multiply(char a[],char b[]){
    static char mul[MAX];
    char c[MAX];
    char temp[MAX];
    int la,lb;
    int i,j,k=0,x=0,y;
    long int r=0;
    long sum = 0;
    la=strlen(a)-1;
    lb=strlen(b)-1;

    for(i=0;i<=la;i++){
            a[i] = a[i] - 48;
    }

    for(i=0;i<=lb;i++){
            b[i] = b[i] - 48;
    }

    for(i=lb;i>=0;i--){
        r=0;
        for(j=la;j>=0;j--){
            temp[k++] = (b[i]*a[j] + r)%10;
            r = (b[i]*a[j]+r)/10;
        }
        temp[k++] = r;
        x++;
        for(y = 0;y<x;y++){
            temp[k++] = 0;
        }
   }

   k=0;
   r=0;
   for(i=0;i<la+lb+2;i++){
        sum =0;
        y=0;
        for(j=1;j<=lb+1;j++){
            if(i <= la+j){
                sum = sum + temp[y+i];
            }
            y += j + la + 1;
        }
        c[k++] = (sum+r) %10;
        r = (sum+r)/10;
   }
   c[k] = r;
   j=0;
   for(i=k-1;i>=0;i--){
      mul[j++]=c[i] + 48;
   }
   mul[j]='\0';
   return mul;

}

Sample output of above code:

Enter the first number: 55555555

Enter the second number: 3333333333

Multiplication of two numbers:

185185183314814815

Logic for multiplication of large numbers

As we know in c there are not any such data types which can store a very large numbers. For example we want to solve the expression:

55555555 * 3333333333

Result of above expression is very big number which beyond the range of even long int or long double. Then question is how to store such a big numbers in c?

Solution is very simple i.e. using array. Above program has used same logic that is we are using as usual logic to multiply two numbers except instead of storing the data in the normal variables we are storing into the array.

like image 28
user3629249 Avatar answered Sep 22 '22 02:09

user3629249