In the C++ function below, why is numbers[max_index1] cast to long long and then multiplied by numbers[max_index2]? I would of thought that you'd multiply the numbers and then cast?
Also would it not make more sense to make the vector numbers type long long instead of int therefore the casting wouldn't be necessary?
long long MaxPairwiseProductFast(const vector<int>& numbers) {
int n = numbers.size();
int max_index1 = -1;
cout << "value at max_index1 is " << numbers[max_index1] << std::endl;
for(int i = 0; i < n; i++)
if((max_index1 == -1) || (numbers[i] > numbers[max_index1]))
max_index1 = i;
int max_index2 = -1;
for(int j = 0; j < n; j++)
if((numbers[j] != numbers[max_index1]) && ((max_index2 == -1) || (numbers[j] > numbers[max_index2])))
max_index2 = j;
return ((long long)(numbers[max_index1])) * numbers[max_index2];
}
int main() {
int n;
cin >> n;
vector<int> numbers(n);
for (int i = 0; i < n; ++i) {
cin >> numbers[i];
}
long long result = MaxPairwiseProductFast(numbers);
cout << result << "\n";
return 0;
}
((long long)(numbers[max_index1])) * numbers[max_index2];
numbers[max_index2] will be promoted to long long before multiplication is performed.
If you multiply two int's and the result overflowed, there is nothing you can achieve by casting that result to long long, so you cast first, then multiply.
Also would be not make more sense to make the vector numbers type long long instead of int therefore the casting wouldn't be necessary?
If you know that the individual numbers will fit an int, but the result of multiplying two int's can overflow, this will help save space.
I woudld of thought that you'd multiply the numbers and then cast?
Imagine your two operands have the value std::numeric_limits<int>::max(). This is the biggest value an int can represent, and (since it's a positive integer) the result of squaring this number is even bigger.
When you multiply two int values, the result is also an int. See here (specifically conversions, integral promotion and overflow of signed types).
Since the result is by definition bigger than the largest value you can store in an int, doing this multiplication with ints gives an undefined result. You need to perform the multiplication with a type large enough to store the result.
Related
How i get the float result of the division?
Although i defined the average array as float.
int main()
{
const int Number = 20;
int Fibonacci[Number];
float average[Number];
for ( int i =0; i <= Number; i++ )
{
if ( i == 0 )
{Fibonacci[i] = 0;}
else if ( i == 1 )
{Fibonacci[i] = 1;}
else
{Fibonacci[i] = Fibonacci[i -1] + Fibonacci[i -2];
//average[i] = (Fibonacci[i -1] + Fibonacci[i -2])/2 ;
}
}
cout<< "The first 20 Fibonacci series numbers are: \n";
for ( int i = 1; i <= Number; i++)
{ cout<< Fibonacci[i]<<endl;
}
cout<< "The average adjacent array numbers are: \n";
for ( int i = 3; i <= Number; i++)
{ average[i] = (Fibonacci[i]/2);
//cout.precision(0);
Here the proplem
cout<< average[i]<<endl; <-----here the problem!!
}
return 0;
}
I appreciate any help.
Thanks in advance.
When you do the division, you are doing an integer division, so you won't get floating point results. A simple fix would be the following:
average[i] = Fibonacci[i] / 2.0f;
Note that if one of the operands to / is a float, then you get floating point division.
Also, note that your loops index too far into the array. You need to stop before Number, like this:
for ( int i = 0; i < Number; i++)
This is because valid array indexes go from 0 .. (Number - 1).
If Fibonacci[i] is of type int, then (Fibonacci[i]/2) is an integral division, resulting in an integral value (without any fractional part). Assigning this integral result to a float does not change the fact that you have performed an integral division.
You can enforce a floating point division by making one of the operands a floating point value.
So (1) use either a cast...
((float)Fibonacci[i])/2
or (2) divide by 2.0f (which is a float value):
Fibonacci[i]/2.0f
Just use typecasting the fibonacci array like this-
average[i] = (float)Fibonacci[i]/2;
Because in order to get float result any of the two variable used in / operation has to be float.
This is my code with int j:
void solve(){
unsigned long long n;
cin>>n;
unsigned long long sum = 0;
int j = 1;
for(int i=3;i<n+1;i+=2){
sum += ((4*i)-4)*(j);
j++;
}
cout<<sum<<"\n";
}
Input:
499993
Output:
6229295798864
but it is giving wrong output, and here is my code with long long j which is working fine:
void solve(){
int n;
cin>>n;
unsigned long long sum = 0;
long long j = 1;
for(int i=3;i<n+1;i+=2){
sum += ((4*i)-4)*(j);
j++;
}
cout<<sum<<"\n";
}
Input:
499993
Output:
41664916690999888
In this case value of j is well below 499993, which is in int range but still, it's not working. Why is it actually happening?
Here is the link to the actual problem. In case, you want to have a look.
Notice that the result of ((4*i)-4)*(j) is an int, since both i and j are int types. The right hand side is promoted to unsigned long long only when adding ((4*i)-4)*(j) to sum. But the expression ((4*i)-4)*(j) already overflows the size of the int type for a large enough n before being promoted.
However, if you change either of i or j to unsigned long long, the expression ((4*i)-4)*(j) is evaluated to unsigned long long, safely inside the size limits.
In the first code snippet in the expression
((4*i)-4)*(j)
of the assignment statement
sum += ((4*i)-4)*(j);
the both operands (4*i)-4) and (j) have the type int. So the type of the expression (the common type of the operands) is also int. But an object of the type int is not large enough to store the result value. So here an overflow takes place.
When the j is declared as having the type long long
long long j = 1;
then the common type of the expression above is also long long. It means that due to the usual arithmetic conversion this operand (4*i)-4) is also converted to the type long long. And an object of this type can store the result value provided for the inputted data.
You can check what are the maximum values that can be stored in objects of the type int and long long.
Here you are.
#include <iostream>
#include <limits>
int main()
{
std::cout << "The maximum value of an object of the type int is "
<< std::numeric_limits<int>::max()
<< '\n';
std::cout << "The maximum value of an object of the type long long is "
<< std::numeric_limits<long long>::max()
<< '\n';
return 0;
}
The program output might look like
The maximum value of an object of the type int is 2147483647
The maximum value of an object of the type long long is 9223372036854775807
I have been trying to learn C++ from a C# background, and I am running in to a very weird mistake in my Maximum Pair Product method.
The method works as expected with small numbers. For products of large numbers it produces a strange rounding and outputs the incorrect output.
int64_t Testing::MaximumPairProductFast(const std::vector<int>& numbers)
{
int64_t largestIntA = 0;
int64_t largestIntB = 0;
for (int i = 0; i < numbers.size(); i++)
{
// find first largest number
if (numbers[i] > largestIntA) largestIntA = numbers[i];
}
for (int i = 0; i < numbers.size(); i++)
{
//find second largest number
if (numbers[i] > largestIntB && numbers[i]!= largestIntA) largestIntB = numbers[i];
}
return largestIntA * largestIntB;
}
The main program
int main()
{
Testing ch;
std::vector<int> test{ 100000,90000 };
int result= ch.MaximumPairProductFast(test);
std::cout << result << "\n";
}
The output of the computation will be 410065408 instead of 9000000000 which is the correct answer
The weird thing is when I try to print this:
std::cout << (int64_t) 100000 * 90000 << "\n";
It does give the correct result 9000000000.
But if I don't cast it to int64_t :
std::cout << 100000 * 90000 << "\n";
The result is 410065408, which is exactly the output from my method even though I have ensured to return an int64_t type.
I have also tried this, but the outcome is the same:
int64_t Test::MaximumPairProductFast(const std::vector<int>& numbers)
{
int64_t largestIntA = 0;
int64_t largestIntB = 0;
for (int i = 0; i < numbers.size(); i++)
{
// find first largest number
if ((int64_t) numbers[i] > largestIntA) largestIntA = (int64_t) numbers[i];
}
for (int i = 0; i < numbers.size(); i++)
{
//find second largest number
if ((int64_t) numbers[i] > largestIntB && (int64_t) numbers[i]!= largestIntA) largestIntB = (int64_t) numbers[i];
}
return largestIntA * largestIntB;
}
Am I missing an obvious detail?
You are truncating your result from a int64_t to an int. On a typical system these days, you'll truncate a 64 bit integer and store it in a 32 bit value.
If you compile with the warning level increased, the compiler will tell you about this problem.
The solution is to declare result with the proper type:
int64_t result = ch.MaximumPairProductFast(test);
Or, just let the compiler use the correct type with auto:
auto result = ch.MaximumPairProductFast(test);
In your second example, the constants 100000 and 90000 are integers, so the multiplication of them will be done as integers. When you case one of the values to int64_t, the multiplication will be done with 64 bit ints. This can also be expressed with 100000LL.
On your system int is a 32-bit integer. int64_t is 64-bit integer. The problem in your code is you are multiplying two 32-bit ints so you're getting a 32-bit int result. Your answer is overflowing. When you explicitly cast it to int64_t, the operands are now 64-bit ints and you're getting a 64-bit int result which can hold the large value and not overflow.
I'll suggest you either:
use std::vector<int64_t> instead of std::vector<int>
If you're worried about space, do as you did, explicitely cast it to 64-bit int and then multiply
I am currently learning C++, so I am a beginner. I thought I'd make a small program to generate the Bessel polynomial terms. This is the program:
#include <iostream>
// x!
long long fact(const long long &x)
{
long long z {1};
for (long long i=1; i<=x; ++i)
z *= i;
return z;
}
// 2^n
long long pwr2(const int &n)
{
long long z {1};
for (long long i=0; i<n; ++i)
z *= 2;
return (n == 0 ? 1 : z);
}
// Bessel coefficients
long long bessel(long long *a, const long long &N)
{
for (long long i=0; i<=N; ++i)
a[i] = fact(N + i) / (pwr2(i) * fact(N - i) * fact(i));
return *a;
}
int main()
{
std::cout << "N = ";
long long N;
std::cin >> N;
long long *a {new long long[N + 1]};
*a = bessel(a, N);
for (long long i=0; i<=N; ++i)
std::cout << a[i] << ( i<N ? " " : "\n");
delete a;
a = nullptr;
return 0;
}
N=10 seems to be the limit. sizeof(long long) shows 8 (archlinux x64). fact(20) > (2^64)-1, so I'm stuck, even with long long. Is there a way to circumvent this limit?
The code, as you see it, is after I got desperate and modified all int to long long. I even added "ll" to all the numbers, there's no effect. I even removed the main parenthesis from the denominator and arranged the terms so that they divide, progressively, to somehow balance themselves, e.g.:
fact(N+i)/fact(N-i)/fact(i)/pwr2(i), also no effect.
You can't do what you want to with native types as they are limited by bit sizes.
However you can use some libraries to accomplish those (This is one such example) if you really need it (But as per your question , you are just learning c++ so I guess you dont need those)
I'm fiddling around with pointers, and as an example, the code:
int foo = 25;
int * bar = &foo;
cout << (unsigned long int) bar;
outputs something around 3216952416 when I run it.
So why does this code output such a low number, or even a negative number, when I run it?
int total = 0, amount = 0;
for( int i = 0; i < 100000; i++ )
{
int foo = 25;
int * bar = &foo;
total += (unsigned long int) bar;
amount++;
}
cout << "Average pointer position of foo: " << total / amount << endl;
It's probably something simple...
First of all, variable addresses (which are a pointer's value) are unsigned. You are using signed integer to make your calculation. It explain that the range is shifted, and negative values can occurs. Secondly you are certainly overflowing when using
total += (unsigned long int) bar;
, so any value is possible.
Your cast is useless, because the type of total is int. There will be another implicit cast performed.
You can try to change the type of total to unsigned long int but this is not enough. to avoid overflow, you need to do the sum of ratio, not the ratio of the sum
double amount = 100000;
double average= 0;
for( int i = 0; i < amount; i++ )
{
int foo = 25;
int * bar = &foo;
average += (((unsigned long int) bar)/amount);
}
cout << "Average pointer position of foo: " << (unsigned long int)average << endl;
int cannot store an infinitely large number. When total becomes too large to store in an int, the value wraps around to the other side of int's range.
On most systems, an int variable is held using 32 bits of memory. This gives it a range of -2147483648 to 2147483647.
If your int already holds a value of 2147483647 and you add 1, the result will be -2147483648!
So, if you want to calculate the "average pointer value", you need to store your sum in something much larger than int, or do your calculations such that you don't need to store the sum of all the pointer values (eg. UmNyobe's answer).