How does int(or long long) overflow in c++ affect modulus? - c++

Suppose I have two long longs, a and b, that I need to multiply, then get the value mod k for some large k, such that a, b, and k are all in the range of long long but not of int. For simplicity, a, b < k.
Thus the code would be:
long long a, b, k;
cin >> a >> b >> k;
cout << (a * b)%k << "\n";
However, since a and b are so large, if you multiply like above, and it overflows and becomes negative, then mod k would be a negative number and incorrect.
How can you ensure that the value mod k is correct?
Edit: As a bonus, how does this work in Java? Is it the same, as expected? Or is BigInteger needed?

Many compilers offer a 128-bit integral type. For example, with g++ you can make a function
static inline int64_t mulmod(int64_t x, int64_t y, int64_t m)
{
return ( (__int128_t)x * y) % m;
}
Aside: if you can, try to stick to unsigned integer types when you're doing modular arithmetic. The rounding behavior of integer division makes using % very awkward when signed values are involved.

If you know the values are less than ULONGLONG_MAX/2 (so an add won't overflow), you can do the multiply one bit at a time:
unsigned long long mulmod(unsigned long long a, unsigned long unsigned long b, long long m) {
unsigned long long rv = 0;
a %= m;
b %= m;
while (b) {
if (b&1) { rv += a; if (rv >= m) rv -= m; }
a += a; if (a >= m) a -= m;
b >>= 1; }
return rv; }
If you know you're running on gcc/x86_64, you could try:
unsigned long mulmod(unsigned long a, unsigned long b, unsigned long m) {
unsigned long rv;
asm ("mulq %2; divq %3" : "=d"(rv), "+a"(a): "S"(b), "c"(m));
return rv;
}
which will work up to ULONG_MAX
If your numbers get bigger than that, you'll need to go to a multiprecision library such as GMP

Related

long long int ans = a*b VS long long int ans = (long long int) a*b

I've written a code:
int a = 1000000000, b = 1000000000;
long long int ans = a * b;
cout << ans << '\n';
this code is causing overflow. I understand that a * b is causing the problem but I have taken long long int variable to keep a*b.
But look at the following code:
int a = 1000000000, b = 1000000000;
long long int ans = (long long int)a * b;
cout << ans << '\n';
it's working fine causing no overflow. Does it make any temporary variable to hold the value when calculating? Please explain the reason behind this strange overflowing.
This makes two temporary variables, (long long int)a and (long long int)b. The second conversion is implicit.
Actual compilers might not bother, if the hardware has a 32*32->64 multiply, but officially the conversions have to occur. On 64 bits hardware, it's essentially free when you load an int in a 64 bit register.

LCM and GCD not working

I made a program for codechef and its wrong apparantly (although all tests have been positive). The code is:
#include <iostream>
using namespace std;
int g (int a,int b){
return b == 0 ? a : g(b, a % b);
}
int l (int a, int b){
return (a*b)/(g(a,b));
}
int main() {
int n;
cin >> n;
int a[n],b[n];
for (int x = 0;x<n;x++){
cin >> a[x] >> b[x];
}
for (int x = 0;x<n;x++){
cout << g(a[x],b[x]) << " "<< l(a[x],b[x]) << endl;
}
return 0;
}
Codechef won't tell me what integers dont work, and im pretty sure my gcd function is legit.
Since gcd is properly defined as the largest non-negative common divisor, you can save yourself the annoying details of signed division, e.g.,
static unsigned gcd (unsigned a, unsigned b)
{
/* additional iteration if (a < b) : */
for (unsigned t = 0; (t = b) != 0; a = t)
b = a % b;
return a;
}
Likewise for lcm; but the problem here is that (a*b) may overflow. So if you have two large (signed) int values that are co-prime, say: 2147483647 and 2147483629, then gcd(a,b) == 1, and (a*b)/g overflows.
A reasonable assumption on most platforms is that unsigned long long is twice the width of unsigned - although strictly speaking, it doesn't have to be. This is also a good reason to use exact types like [u]int32_t and [u]int64_t.
One thing you can be sure of is that a/g or b/g will not cause any issues. So a possible implementation might be:
static unsigned long long lcm (unsigned a, unsigned b)
{
return ((unsigned long long) a) * (b / gcd(a, b)));
}
If your test values are 'positive' (which is what I think you mean), you can cast them prior to (unsigned) prior to call. Better yet - replace all your int variables with unsigned int (though the loop variables are fine), and save yourself the trouble to begin with.

Unsigned long long Fibonacci numbers negative?

I've written a simple Fibonacci sequence generator that looks like:
#include <iostream>
void print(int c, int r) {
std::cout << c << "\t\t" << r << std::endl;
}
int main() {
unsigned long long int a = 0, b = 1, c = 1;
for (int r = 1; r <= 1e3; r += 1) {
print(c, r);
a = b;
b = c;
c = a + b;
}
}
However, as r gets around the value of 40, strange things begin to happen. c's value oscillate between negative and positive, despite the fact he's an unsigned integer, and of course the Fibonacci sequence can't be exactly that.
What's going on with unsigned long long integers?
Does c get too large even for a long long integer?
You have a narrowing conversion here print(c, r); where you defined print to take only int's and here you pass an unsigned long long. It is implementation defined.
Quoting the C++ Standard Draft:
4.4.7:3: If the destination type is signed, the value is
unchanged if it can be represented in the destination type; otherwise,
the value is implementation-defined.
But what typically happens is that: from the unsigned long long, only the bits that are just enough to fit into an int are copied to your function. The truncated int is stored in Twos complements, depending on the value of the Most Significant Bit. you get such alternation.
Change your function signature to capture unsigned long long
void print(unsigned long long c, int r) {
std::cout << c << "\t\t" << r << std::endl;
}
BTW, see Mohit Jain's comment to your question.

A strange C++ error, maybe it is relative to the long long type

My code is the following:
#include <iostream>
int gcd(int a, int b) {
//write your code here
if(a==0){
return b;
}else if(b==0){
return a;
}else if(a>b){
int a_pri=a%b;
return gcd(b,a_pri);
}else if(a<b){
int b_pri=b%a;
return gcd(a,b_pri);
}else{
return a;
}
}
long long lcm(int a, int b) {
int temp_gcd = gcd(a,b);
long long abproduct = a*b;
long long result = abproduct/temp_gcd;
return result;
}
int main() {
int a, b;
std::cin >> a >> b;
std::cout << lcm(a,b) << std::endl;
return 0;
}
I would like to output the largest common multiple of two numbers.
but as I input two numbers 14159572 63967072 ,It output a negative number -527892768.But the correct answer should be 226436590403296.
It looks like the output is cut off to 32bit.
so ,I print the variable temp_gcd ,it is 4.I changed the expression
long long result = abproduct/temp_gcd;
to
long long result = abproduct/4;
Then it outputs the right answer.
The problem is on the line long long abproduct = a*b;
Since a and b are both int, any operation on them will result in an int, which will result in an overflow in this case. Try casting either a or b to long long when doing the calculation.
long long abproduct = (long long)a * b;
You're performing an int multiplication because that's the data type of the operands. Change that data type. I.e., change
long long lcm(int a, int b)
to
long long lcm(long long a, long long b)
Don't take the advice to use casts: a cast should always be the measure of last resort, like going to war (only after politicians and diplomats fail).
If you don't change the function signature then you can force a conversion by replacing a*b with 1LL*a*b. But I don't recommend that here. Using proper data types is the right way to go.
Still, the code
long long abproduct = a*b;
long long result = abproduct/temp_gcd;
needlessly adds cases where the result can overflow. To reduce that,
long long result = a*(b/temp_gcd);
noting that this can't discard information (in general, though, you have to be careful about integer division discarding information).
Didn't want to edit the #MahlerFive's answer - that should work too. I would cast a and b to long long like-so: long long abproduct = static_cast<long long>(a)*static_cast<long long>(b).

Calculation of digits in 10^9 in C++

I was trying to find the lcm of two numbers and for one of the input cases (28851539 and 1183019) my program returns a negative value . Apparently it is not able to compute (28851529*1183019)/9 .
#include <iostream>
long long gcd(int a, int b) {
long long int temp;
if(a%b==0)
{
return b;
}
else
{
temp=a%b;
return gcd(b,temp);
}
}
long long lcm(int a, int b , int g) {
//std::cout<<g;
long long int f=(a*b)/g;
return f;
}
int main() {
long long int a, b;
std::cin >> a >> b;
long long int g = gcd(a,b);
long long int q=lcm(a, b, g);
std::cout << q << std::endl;
return 0;
}
How do i compute that accurately ?
You problem is
long long int f=(a*b)/g;
since all of the types in (a*b)/g are int then this will be calculated as an int and if an int is 16 or 32 bits then it will overflow. Do note that since you have signed types this is actually undefined behavior. To get around this you either need to make a, b or g a long long int or you can change the parameters of the function to make them all long long ints.
long long int lcm(long long int a, long long int b , long long int g)
I would also suggest you use an unsigned long long int if you are not dealing with negative numbers. If you are not then you can use the type uint64_t from <cstdint> otherwise int64_t to make the type names shorter.