C++ integer multiplication: explain this behaviour - c++

I wrote a simple function in C++ to calculate the volume of a Box object which has a length, breadth, and height. This is part of a class, so l,b,h are private members:
long long CalculateVolume(){
return l*b*h;
}
This does not work correctly with large values of l,b,h. In my case l = 1039, b = 3749, h = 8473. The result was
-1355615565
I thought this was due to overflow, so I tried
unsigned long long CalculateVolume(){
return l*b*h;
}
but the result was
18446744072353936051
Finally, what worked was to multiply the integers in steps:
long long CalculateVolume(){
long long result = l;
result *= b;
result *= h;
return result;
}
which gave the correct result of 33004122803. I don't understand why this solution works. Can you explain what happens under the hood in each of the three cases? Thank you!

If you variables l, b, and h are long long then the behaviour of both snippets would be identical.
However, if the variables are ints, then in the first snippet
return l * b * h;
would result in an overflow. The conversion to long long would only happen when the result is returned, which is too late.
In this snippet
long long result = l;
result *= b; // multiplying 'int' and 'long long' is like multiplying 2 'long long's
result *= h;
return result;
you are only ever multiplying long longs, so you don't overflow.
You could make your variables long long to begin with, or cast the variables before multiplying.

I think that the types of your 3 variables:l, b, and h are responsible for the wrong behavior, if they are integers values, their multiplication is an integer as well. So you have to cast them to long long or unsigned long long before multiplying. Or like you did in the last snippet of code, you can cast only one of them and then the multiplication will have the biggest type between the factors (which is in that case long long)

Related

C++ calculation of long long with int

below you can find a part of my C++ code of a box class.
When I want to calculate the volume for
l=1039
b=3749
h=8473
I am expecting 33004122803.
Unfortunately I do not understand why only the first implementation (CalculateVolume1) gives the correct answer.
The other two calculations result in -1355615565.
Can someone please help me to understand why this is the case?
class Box{
private:
int l,b,h;
public:
//works
long long CalculateVolume1() { return (long long) l*b*h;}
// does not work
long long CalculateVolume2() { return long long v = l*b*h;}
//does not work
long long CalculateVolume3()
{
long long v = long long (l)* long long(b)* long long (h);
return v;
}
};
In the first one, (long long) l*b*h, the cast applies to l, as if it had been written ((long long)l)*b*h. So l gets converted to long long. And since one of the factors in the multiplication is long long, the other two are promoted to long long and the result of the multiplication is correct.
"Fixing" the syntactic errors in the second and third,
long long v = l*b*h;
here, the type of all three factors is int, so the multiplication is done on ints, and the result overflows.
long long v = (long long)l*(long long)b*(long long)h;
this is essentially the same as the first: all three factors are promoted to long long, this time by explicit casts on all three, so the result is calculated using long long arithmetic, and the result fits.
The problem with the second one as written is that you can't define a variable inside a return statement. So
return long long v = l; // illegal
should be:
long long v = l;
return v;
The problem with the third one as written is that a function-style cast has to have a name that's a single word:
long long v = int(l); // okay, but pointless
long long v = long long(l); // error, invalid name
could be:
typedef long long my_type;
long long v = my_type(l); // okay

please explain this weird behaviour c++ multiplying numbers then mod

i have less experience with c++ and i code mainly in python. while solving some programming challenge online there was a part of code where i have to multiply two numbers and reduced it with mod.
v = (u*node) % 100000
where u and node are int values with range 1 - 100000. Due to time limit issues i wrote my code in c++. Here what i wrote
long long v = (u * node) % 100000;
while submitting i got runtime error in all the test cases. I downloaded failed test cases and ran in my local computer and i was getting perfect output.
After seeing editorial, i change that line to something like this
long long v = u;
v = (v*node) % 100000;
and submitted. I passed all the test cases. Please can anyone explain whats the difference between those two lines..
variable data types -
int u
int node
Because u and node are both ints, this expression,
(u * node)
produces an int result. If it overflows—meaning that the result is too large to fit in an int—too bad. Signed integer overflow is undefined behavior, and all bets are off. Chances are, it'll do something like wrap around, but it could also format your hard disk.
When you make u a long long int, then the same expression produces a long long int result. The node multiplicand gets implicitly promoted to a long long int (int to long long int is a widening conversion, so it is always safe), and then these two long long int values get multiplied. This operation won't overflow, so you avoid undefined behavior and get the correct result.
You could have also written the code with an explicit cast to avoid the declaration of a new variable:
(static_cast<long long int>(u) * node)
Note that it doesn't matter which value you promote, the result will be the same because the other value will get implicitly promoted, as described above:
(u * static_cast<long long int>(node))
On the other hand, this won't work:
static_cast<long long int>(u * node)
because it only widens the result of the multiplication operation, after the multiplication has been performed. If that multiplication overflowed the int type, then it is already too late.
It is the same reason that this doesn't work—the promotion to long long happens after the result is evaluated as an int:
long long v = (u * node)
Please can anyone explain whats the difference between those two lines..
first line actually mean:
long long v = (long long) (int * int % int);
so, first you multiply int by int, get overflow, truncate to int, mod, extend int to long long
next line actual mean:
long long v = (long long) int;
v = long long * int % int;
so, first extend int to long, multiple long by int, no overflow, mod, assign to long long
Probably you were running into an overflow in the first case (both u and v as ints). This happens because when multiplying variables, the compiler will keep the result in a temporary variable that has the same type of the highest type (int, floats, doubles, etc) of the variable in the multiplication. So, if you are multiplying two big integers, the result can overflow.
Your modification works because the temporary result is stored in a long long, which does not overflow in your examples.

Why does implicit conversion of int to long long int give unexpected answer in C++?

I read that conversion from int to long long int is promotion and hence thought that there shouldn't be any issue as there is no loss of data, unlike the vice versa conversion.
But when I multiply two ints of large value and store it in long long int, it is showing me negative number.
Eg:
int a=1000000, b=1000000;
long long int c=a*b;
cout<<c;
The above code gives me a negative value. Can someone explain why?
a*b is still of type int. Once it's evaluated, the result is then converted to long long int. At that point it's too late to avoid overflow. Convert one of your values to long long int before preforming the multiplication. Try this :
#include <iostream>
int main()
{
int a = 1000000, b = 1000000;
long long int c = static_cast<long long int>(a)*b;
std::cout << c;
return 0;
};
The multiplication is happening as an int, which overflows, giving Undefined Behaviour (in this case overflow, which is very normal - your combination of compiler+settings may even guarantee it), and after that the result is being converted to long long.
I think you want to do the conversion on one of the arguments before multiplication, so that the multiplication is performed using long longs:
long long c = static_cast<long long>(a)*b;
In this way, b will be promoted to long long before the multiplication takes place, and the whole operation will be performed safely, and with the desired result.
Because multiplying two ints will result in another int that comes with all the overflow problems attached. This int is then (after the fact) promoted to a long long int which still means it's not what you want.
Promote at least one of the operands to have the other promoted and get the result you want.

How to represent large number in c++

I am trying to represent some large numbers in c++. In the below code if tried only to print s the compiler would not complain. But If try to make some multiplications and storing it in t the compiler would say integer overflow in expression...
I tried to make it unsigned long long t but again the compiler complains. Is there any way in doing this multiplication without having any overflow?
int main ()
{
long long int s = 320718425168;
long long int t = 4684688*68461; //4684688*68461 = 320718425168
return 0;
}
The literals used as the factors of the products are of type int, which cannot represent the product.
Cast one of the factors to long long first.
long long t = (long long)4684688 * 68461;
Or use the corresponding literal suffix ll or LL to change the literals type. I.e.
long long t = 4684688LL * 68461;
Demo.

Cannot understand the difference between these two code samples

I wanted to write a program that computes the number of zones made by n lines.
The first example is my code, and the second is my friend's code. I think they are trying to do the same thing, but for the case n=65535 my code gives me the wrong answer. Where is the problem in my code?
my code:
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
unsigned long long ans;
ans = (n*(n + 1) / 2) + 1;
cout << ans << endl;
return 0;
}
my friend's code:
#include <iostream>
using namespace std;
int main(void){
double n,sum;
cin>>n;
sum=n*(n+1)/2+1;
cout<<(long)sum<<endl;
return 0;
}
In your code:
int n;
ans = (n*(n + 1) / 2) + 1;
All values in the calculation are ints: n is declared as int, and plain integer constants are ints as well. Therefore the result of this calculation will also be an int. The fact that you later assign this result to a long long variable doesn't change this.
Now the result of the multiplication 65535*65536 does not fit in a 32-bit signed int, so you get a nonsense answer. Fix your program by making n a 64-bit long long.
As #Dithermaster suggests, the problem here is probably one of integer overflow.
As it stands right now, your code doesn't actually make much sense. In particular, since you've defined n as an int, and all the integer literals in the expression: (n*(n + 1) / 2) + 1 are also small enough to fit in an int, the calculation will be carried out on ints, and then (after the calculation is complete) the result will be converted to long long and assigned to ans (because you've defined ans as a long long).
What you almost certainly want is to carry out the entire calculation on long long to avoid overflow. The most obvious way to do this would be to define n as a long long instead of an int.
Your friend has avoided this by defining n as a double. This works up to a point--a typical implementation of double has a 53-bit significand, so it can be used as (essentially) a 53-bit integer type. That's obviously quite a bit more than the 16 bits that's mandated for an int, but equally obviously less than the 64 bits mandated for a long long.
There's also no point in supporting n being negative, so you could consider defining n and ans as unsigned long long instead.