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

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.

Related

C++ integer multiplication: explain this behaviour

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)

What data type is used to store intermediate calculations while executing a program in C++?

I was trying to do the following calculations but found out that the calculations do not yield the correct result.
I have the following doubt that when my computer does the calculation a*b, what data type is used to store the result of the calculation temporary before doing the modulus. How is the data type in which it stores the result decided?.
Please do let me know about the source of the information.
#include <iostream>
using namespace std;
int main()
{
long long int a=1000000000000000000; // 18 zeroes
long long int b=1000000000000000000;
long long int c=1000000007;
long long int d=(a*b)%c;
cout<<a<<"\n"<<b<<"\n"<<c<<"\n"<<d;
}
Edit1: This code also gives incorrect output
#include <iostream>
using namespace std;
int main()
{
int a=1000000000; // 9 zeroes
int b=1000000000;
long long int c=1000000007;
long long int d=a*b%c;
cout<<a<<"\n"<<b<<"\n"<<c<<"\n"<<d;
}
How is the data type in which it stores the result decided?
The rules are fairly complicated and convoluted in general, but in this particular case it's simple. a*b is of type long long, and since a*b overflows the programs has Undefined Behavior.
You can use the equivalent formula to compute the correct result (without overflowing):
(a * b) % c == ((a % c) * (b % c)) % c
Could you also suggest on how to decide for mixed data types and post
about your source of information
Of some interest: https://en.cppreference.com/w/cpp/language/implicit_conversion The standard rules are unfortunately even more complicated.
As some suggestions:
never mix unsigned and signed.
pay attentions that types smaller than int will be promoted to int or unsigned.
for a type T equal or larger than int then T op T will have type type T. This is what you should be aiming for in your expressions. (i.e. have both operators of the same type either int, long or long long.
avoid unsigned types. Unfortunately that's impossible with the current Standard Library design (std::size_t sigh)
avoid long as its width differs between current major compilers and platforms
if you care about the width of the integer data type then avoid int long long long and such and always use fixed width integer types (std::int32_t std::int64_t etc.). Completely ignore that technically those types are optional.
My understanding is that long long has to be able to accommodate at least 64 bits but each 1000000000000000000 is a 60 bit number so a*b would yield a result that exceeds any integer representation the compiler supports. Perhaps you were thinking that the 1000000000000000000 was binary?

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.

long long value in Visual Studio

We know that -2*4^31 + 1 = -9.223.372.036.854.775.807, the lowest value you can store in long long, as being said here: What range of values can integer types store in C++.
So I have this operation:
#include <iostream>
unsigned long long pow(unsigned a, unsigned b) {
unsigned long long p = 1;
for (unsigned i = 0; i < b; i++)
p *= a;
return p;
}
int main()
{
long long nr = -pow(4, 31) + 5 -pow(4,31);
std::cout << nr << std::endl;
}
Why does it show -9.223.372.036.854.775.808 instead of -9.223.372.036.854.775.803? I'm using Visual Studio 2015.
This is a really nasty little problem which has three(!) causes.
Firstly there is a problem that floating point arithmetic is approximate. If the compiler picks a pow function returning float or double, then 4**31 is so large that 5 is less than 1ULP (unit of least precision), so adding it will do nothing (in other words, 4.0**31+5 == 4.0**31). Multiplying by -2 can be done without loss, and the result can be stored in a long long without loss as the wrong answer: -9.223.372.036.854.775.808.
Secondly, a standard header may include other standard headers, but is not required to. Evidently, Visual Studio's version of <iostream> includes <math.h> (which declares pow in the global namespace), but Code::Blocks' version doesn't.
Thirdly, the OP's pow function is not selected because he passes arguments 4, and 31, which are both of type int, and the declared function has arguments of type unsigned. Since C++11, there are lots of overloads (or a function template) of std::pow. These all return float or double (unless one of the arguments is of type long double - which doesn't apply here).
Thus an overload of std::pow will be a better match ... with a double return values, and we get floating point rounding.
Moral of the story: Don't write functions with the same name as standard library functions, unless you really know what you are doing!
Visual Studio has defined pow(double, int), which only requires a conversion of one argument, whereas your pow(unsigned, unsigned) requires conversion of both arguments unless you use pow(4U, 31U). Overloading resolution in C++ is based on the inputs - not the result type.
The lowest long long value can be obtained through numeric_limits. For long long it is:
auto lowest_ll = std::numeric_limits<long long>::lowest();
which results in:
-9223372036854775808
The pow() function that gets called is not yours hence the observed results. Change the name of the function.
The only possible explaination for the -9.223.372.036.854.775.808 result is the use of the pow function from the standard library returning a double value. In that case, the 5 will be below the precision of the double computation, and the result will be exactly -263 and converted to a long long will give 0x8000000000000000 or -9.223.372.036.854.775.808.
If you use you function returning an unsigned long long, you get a warning saying that you apply unary minus to an unsigned type and still get an ULL. So the whole operation should be executed as unsigned long long and should give without overflow 0x8000000000000005 as unsigned value. When you cast it to a signed value, the result is undefined, but all compilers I know simply use the signed integer with same representation which is -9.223.372.036.854.775.803.
But it would be simple to make the computation as signed long long without any warning by just using:
long long nr = -1 * pow(4, 31) + 5 - pow(4,31);
As a addition, you have neither undefined cast nor overflow here so the result is perfectly defined per standard provided unsigned long long is at least 64 bits.
Your first call to pow is using the C standard library's function, which operates on floating points. Try giving your pow function a unique name:
unsigned long long my_pow(unsigned a, unsigned b) {
unsigned long long p = 1;
for (unsigned i = 0; i < b; i++)
p *= a;
return p;
}
int main()
{
long long nr = -my_pow(4, 31) + 5 - my_pow(4, 31);
std::cout << nr << std::endl;
}
This code reports an error: "unary minus operator applied to unsigned type, result still unsigned". So, essentially, your original code called a floating point function, negated the value, applied some integer arithmetic to it, for which it did not have enough precision to give the answer you were looking for (at 19 digits of presicion!). To get the answer you're looking for, change the signature to:
long long my_pow(unsigned a, unsigned b);
This worked for me in MSVC++ 2013. As stated in other answers, you're getting the floating-point pow because your function expects unsigned, and receives signed integer constants. Adding U to your integers invokes your version of pow.

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.