I was trying to find product of some long long integer (0<=a[i]<=10^18)t. now how do i find that the product exeeds 10^18? does the product turn into negetive number (product<0)?
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
long long a[n],product=1;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
for(auto i:a){
product*=i;
if(i==0) break;
if(product>1000000000000000000) {
cout<<-1;
return 0;
}
}
cout<<product;
}
If you are to check against potential overflow, I would advise you to rely on std::numeric_limits<>::max()
(from the <limits>
header) instead of a power of 10
(because the latter eliminates (a lot) of valid values).
Another advantage is portability. Indeed, in your code, you assume that long long
is 8 bytes long which may not always be the case on another platform. Using std::numeric_limits<>::max()
would guarantee to get the right maximum for the specified numeric type.
"Does the product turn into negative number ?"
Actually, signed overflow is Undefined Behaviour so anything can happen. It may be negative, it may not, old legends say that you can even get demons flying out of your nose :D
In case of Undefined Behaviour, it's pointless to reason about the behaviour of the program, unless we look at the generated assembly code to see what will really happen.
"How do I find that the product doesn't overflow ?"
In other words, the question is, how to check if a * b > max
? (where max
is std::numeric_limits<long long>::max()
).
Well, as written, you can't, because by definition, you cannot represent anything higher than max
and evaluating a*b
would be undefined behaviour anyway.
But the above test can be rewritten as a > max / b
(with b != 0
). We turned the multiplication into a division, and consequently the test is now evaluable without overflow.
To avoid clutter in your code, you could perform the test into a dedicated function. Such function might be defined as follows:
#include <concepts>
#include <limits>
#include <cmath>
template <std::integral T>
bool verify_product_range(T a, T b)
{
return (!b || std::abs(a) <= std::numeric_limits<T>::max()/std::abs(b)); // Returns false if a*b overflows, true otherwise.
}
Note: For the above example, the validity range excludes std::numeric_limits<T>::min()
. See here for a more complete version (or below).
A more complete version of the above example (taking into account std::numeric_limits<>::min()
as well in the validity range) might be:
template <std::integral T>
bool verify_product_range(T a, T b)
{
if(!b || !a)
return true; // zero is always valid
if(a/b > 0) // If the product is positive
return (std::abs(a) <= std::numeric_limits<T>::max()/std::abs(b));
else // else (if the product is negative)
{
if(b < 0) std::swap(a, b);
return (a >= std::numeric_limits<T>::min()/b);
}
}