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
Related
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)
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.
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.
I have to store a long double variable in JSON format. JSON supports double variables but not long double. Then I have to split the long double value in several double values, but I don't know how to do that easily.
I already did that for long long int variables by this way :
std::vector<long int> long_long_int__to__long_int(long long int x)
{
std::vector<long int> split;
const unsigned long int n = sizeof(long long int) / sizeof(long int);
for(unsigned long int i = 1; i < n; ++i)
{
split.push_back((long int)(x % (long long int)std::numeric_limits<long int>::max));
x /= (long long int)std::numeric_limits<long int>::max;
}
split.push_back(x);
return split;
}
Any idea how to do that with floating points variables ?
Here is the solution I can think of, and it's applicable to your long long int problem as well.
consider any type you want to store as a array of hex values, whether it's a long long int or long double.
choose one Binary-to-text encoding algorithm and use it to convert the array to a readable string.
store the string to JSON
Store two doubles: (double)x and (double)(x - (double)x). (And pay attention to compilers bugs and switches affecting the handling of precision, they may cause issues when using such techniques, a gcc bug for instance).
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.