sqrt function in C++ issue - c++

#include <iostream>
#include <cmath>
using namespace std;
int main(){
int n;
cin >> n;
int i = sqrt(1 + 2 * n * (n + 1)) - 1;
cout << i;
}
I have written a simple program which utilizes the sqrt() function in C++. The above program prints out a negative value on the console for n = 32768 even though the input to sqrt() is positive. I tried changing the statement from int i = sqrt(1 + 2 * n * (n + 1)) - 1; to
double i = sqrt(1 + 2 * n * (n + 1)) - 1; but the error is not resolving.
Output:
32768
-2147483648
The above output is for int i = sqrt(1 + 2 * n * (n + 1)) - 1;
Please help!

Change int n to double n. Your calculation 1 + 2 * n * (n + 1) overflows the range of int which for 32bits is -2,147,483,648 to 2,147,483,647.
Side note: int may not be 32bit, it depends on the platform (however, usually most of the time it is 32bit)

Related

How to fix "PI recursive function" code to work with all values of n?

I'm working on a code that calculates PI with n terms. However, my code only works correctly with some values of n.
This piece of code even numbers do not work and when I switch up the negative sign the odd numbers do not work.
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
For n = 2 I expected a result of 3.1333 but I got a value of 2.86667
This is the formula for calculating PI , y is the denominator and n is the number of terms
Firstly, I will assume that a complete runnable case of your code looks like
#include <iostream>
using namespace std;
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
I believe that you are attempting to compute pi through the formula
(pi - 3)/4 = \sum_{k = 1}^{\infty} (-1)^{k+1} / ((2k(2k+1)(2k+2)),
(where here and elsewhere I use LaTeX code to represent mathy things). This is a good formula that converges pretty quickly despite being so simple. If you were to use the first two terms of the sum, you would find that
(pi - 3)/4 \approx 1/(2*3*4) - 1/(4*5*6) ==> pi \approx 3.13333,
which you seem to indicate in your question.
To see what's wrong, you might trace through your first function call with PI(2, 2). This produces three terms.
n=2: 2 % 2 == 0, so the first term is -4/(2*3*4) + PI(1, 4). This is the wrong sign.
n=1: 1 % 2 == 1, so the second term is 4/(4*5*6), which is also the wrong sign.
n=0: n == 0, so the third term is 3, which is the correct sign.
So you have computed
3 - 4/(2*3*4) + 4/(4*5*6)
and we can see that there are many sign errors.
The underlying reason is because you are determining the sign based on n, but if you examine the formula the sign depends on y. Or in particular, it depends on whether y/2 is odd or even (in your formulation, where you are apparently only going to provide even y values to your sum).
You should change y and n appropriately. Or you might recognize that there is no reason to decouple them, and use something like the following code. In this code, n represents the number of terms to use and we compute y accordingly.
#include <iostream>
using namespace std;
double updatedPI(int n)
{
int y = 2*n;
if (n == 0) { return 3; }
else if (n % 2 == 1)
{
return 4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
else
{
return -4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
}
int main() {
double n = updatedPI(3);
cout << n << endl;
}
The only problem with your code is that y is calculated incorrectly. It has to be equal to 2 * n. Simply modifying your code that way gives correct results:
Live demo: https://wandbox.org/permlink/3pZNYZYbtHm7k1ND
That is, get rid of the y function parameter and set int y = 2 * n; in your function.

C++ compound assignment and type conversion issue

I am calculating combination(15, 7) in C++.
I first used the following code and get the wrong answer due to a type promotion error.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 2520
So I changed ans *= (a + 1 - i) / i; to ans *= (double)(a + 1 - i) / i; and still get the wrong answer.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (double) (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 6434
Finally, I tried ans = ans * (a + 1 - i) / i, which gives the right answer.
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans = ans * (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
Output: 6435
Could someone tell me why the second one did not work?
If you print out ans without casting it to (int) you'll see the second result is 6434.9999999999990905052982270717620849609375. That's pretty darn close to the right answer of 6535, so it's clearly not a type promotion error any more.
No, this is classic floating point inaccuracy. When you write ans *= (double) (a + 1 - i) / i you are doing the equivalent of:
ans = ans * ((double) (a + 1 - i) / i);
Compare this to the third version:
ans = ans * (a + 1 - i) / i;
The former performs division first followed by multiplication. The latter operates left to right and so the multiplication precedes the division. This change in order of operations causes the results of the two to be slightly different. Floating point calculations are extremely sensitive to order of operations.
Quick fix: Don't truncate the result; round it.
Better fix: Don't use floating point for integral arithmetic. Save the divisions until after all the multiplications are done. Use long, long long, or even a big number library.
First one did not work because you have integer division there.
Difference btw second one and third one is this:
ans = ans * (double(a + 1 - i) / i); // second is equal to this
vs:
ans = (ans * (a + 1 - i)) / i; // third is equal to this
so difference is in order of multiplication and division. If you round double to integer instead of simply dropping fractional part you will get the same result.
std::cout << int( ans + 0.5 ) << std::endl;

C++ Theta function implementation

I am trying to implement this function:
but it's not working. A minimal, verifiable example looks like:
#include <iostream>
#include <cmath>
int main()
{
int N {8}; // change this for testing <1..inf>
double q {0.1 / N};
int countN {static_cast<int>(floor(N / 2))};
static const double PI {3.1415926535897932384626433832795};
// Omega[i] = Theta1(u,m) / Theta4(u,m)
double Omega[countN];
for (int i=0; i<countN; ++i)
{
double micro {!(N % 2) * 0.5}; // 0 for odd N, 1/2 for even N
double num[countN] {sin(PI / N * (i + 1 - micro))};
double den[countN] {0.5};
for (int m=1; m<4; ++m)
{
num[i] += pow(-1, m) * pow(q, m*(m + 1)) * sin((2 * m + 1) * PI / N * (i + 1 - micro));
den[i] += pow(-1, m) * pow(q, m*m) * cos(2 * m * PI / N * (i + 1 - micro));
}
Omega[i] = fabs(pow(q, 0.25) * num[i] / den[i]);
std::cout << " " << Omega[i] << "\n";
}
// testing the values, they should be increasing in value
for (const auto &elem: Omega)
std::cout << elem << " ";
std::cout << "\n";
return 0;
}
There is a minor simplification compared to the original: I factored 2 in both numerator and denominator and I used only the q^0.25 outside of the fraction. Also, countN is the r from the original document, micro is only the 1/2 for even N or 0 for odd N, and i is 0 for array's index but i+1 for calculations, but these shouldn't matter overall.
I tried this with wxMaxima:
Theta[1](x,y):=2*y^0.25*sum( (-1)^k*y^(k*(k+1))*sin((2*k+1)*x),k,0,n );
Theta[4](x,y):=1+2*sum( (-1)^k*y^(k^2)*cos(2*k*x),k,1,n );
n:4$
N:8$
a:0.05$
b(i):=%pi/N*(i-(1-mod(N,2))/2)$
for N:8 thru 9 do for i:1 thru N/2 do print(["N=",N,"i=",i],Theta[1](b(i),a)/Theta[4](b(i),a)),numer;
And the results, in C++:
(q=0.05; N=8)
Omega[0]=0.2018370065366672
Omega[1]=0.06058232646142273
Omega[2]=0.01205653570636574
Omega[3]=0.02127667733703158
(q=0.05; N=9)
Omega[0]=0.348078726440638
Omega[1]=0.1178366281313341
Omega[2]=2.559808325080287e-07
Omega[3]=0.02178788541277828
and in wxMaxima:
["N=",8,"i=",1]" "0.2018370065366672" "
["N=",8,"i=",2]" "0.5439269564954693" "
["N=",8,"i=",3]" "0.7569342043740249" "
["N=",8,"i=",4]" "0.850913653939989" "
["N=",9,"i=",1]" "0.348078726440638" "
["N=",9,"i=",2]" "0.6165773889432575" "
["N=",9,"i=",3]" "0.7800391631077094" "
["N=",9,"i=",4]" "0.8532352152763631
To my surprise, the first term is good, for bith N, so I can't tell what in my code is not right. Could someone help me spot the error?
To be clear about it: I am a beginner in C++ and I am not looking for someone to do it for me, but to let me know of my erros in coding (translating math to C++ code).
You had
double den[countN] {0.5};
this initializes the first element of den to 0.5 and all the other elements to 0.0 (default initialization). In other words, the above is equivalent to
double den[countN] {0.5, 0.0, 0.0, 0.0};
with as many zeros as necessary to fill the array. You probably wanted to initialize all the elements to 0.5. In your case, the easiest way to do that is when you first use that element - or, since you access only the single element den[i] during the lifetime of den, make it a plain double rather than an array:
for (int i=0; i<countN; ++i) {
double micro {N % 2 ? 0.0 : 0.5}; // 0 for odd N, 1/2 for even N
double num{sin(PI / N * (i + 1 - micro))};
double den{0.5};
for (int m=1; m<4; ++m) {
num += pow(-1, m) * pow(q, m*(m + 1)) * sin((2 * m + 1) * PI / N * (i + 1 - micro));
den += pow(-1, m) * pow(q, m*m) * cos(2 * m * PI / N * (i + 1 - micro));
}
Omega[i] = fabs(pow(q, 0.25) * num / den);
}

Codeforces 268B - Unknown value as output for this small C++ program

Here is C++ code for a Codeforces problem I'm trying to solve:
#include <iostream>
using namespace std;
int main()
{
int n = -1;
unsigned long long possible_combinations = 0;
cin >> n;
possible_combinations = (((n - 1) * n * (n + 1)) / 6) + n;
cout << possible_combinations;
return 0;
}
where 1 <= n <= 2000.
It calculates correct value for small values of n, but when I use 2000, it shows - 18446744073611230851. I have tried only a few test cases.
I know the formula is correct and the program should give 1333335000 as output, but it doesn't. What is the problem with the code?
When you perform arithmetic, the result isn't promoted to a wider type if it gets too large.
Since n is an int, and 1 and 6 are ints, the entire calculation is done with int.
1999 * 2000 * 2001 is so large - 7,999,998,000 - that an int overflows.
Use unsigned long long throughout.
Try this:
possible_combinations = (((unsigned long long) (n - 1) * n * (n + 1)) / 6) + n;
The reason of the problem is simple: (n - 1) * n * (n + 1) is too big for int if n==2000 (but your n is int, so this expression returns int). So, you can ask compiler to use bigger type (language can't make type wider automatically) or just change type of n (use unsigned long longn = -1; instead of int n = -1;).

Dereferencing pointer with same adress returns different result

Here's my code:
#include "stdafx.h"
#include "math.h"
#include <iostream>
using namespace std;
double Calc_H(double Q, double Head, double *constants)
{
return (constants[0] * pow(Q, 4) + constants[1] * pow(Q, 3) + constants[2] * pow(Q, 2) + constants[3] * Q + constants[4] - Head);
}
double Calc_dH(double Q, double *constants)
{
return (4 * constants[0] * pow(Q, 3) + 3 * constants[1] * pow(Q, 2) + 2 * constants[2] * Q + constants[3]);
}
double NewtonRaphson(double Head, double first_guess, double max_error, double * constants)
{
double Q_iter = first_guess;
int iter_counter = 1;
cout << constants << endl << constants[0] << endl << constants[1] << endl;
while (abs(Calc_H(Q_iter, Head, constants)) > max_error || iter_counter > 1000)
{
Q_iter = Q_iter - Calc_H(Q_iter, Head, constants) / Calc_dH(Q_iter, constants);
iter_counter++;
}
return Q_iter;
}
double * Calc_constants(double freq)
{
double * pointer;
double constants[6];
constants[0] = -1.2363 + 2.3490 / 10 * freq - 1.3754 / 100 * pow(freq, 2) + 2.9027 / 10000 * pow(freq, 3) - 2.0004 / 1000000 * pow(freq, 4);
constants[1] = 1.9547 - 4.5413 / 10 * freq + 3.5392 / 100 * pow(freq, 2) - 8.1716 / 10000 * pow(freq, 3) + 5.9227 / 1000000 * pow(freq, 4);
constants[2] = -5.3522 - 4.5413 / 10 * freq - 1.3311 / 100 * pow(freq, 2) + 4.8787 / 10000 * pow(freq, 3) - 4.8767 / 1000000 * pow(freq, 4);
constants[3] = 3.8894 / 100 + 3.5888 / 10 * freq + 1.0024 / 100 * pow(freq, 2) - 5.6565 / 10000 * pow(freq, 3) + 7.5172 / 1000000 * pow(freq, 4);
constants[4] = -8.1649 + 5.4525 / 10 * freq - 3.2415 / 100 * pow(freq, 2) + 8.9033 / 10000 * pow(freq, 3) - 9.0927 / 1000000 * pow(freq, 4);
constants[5] = 2.1180 / 10 + 5.0018 / 100 * freq + 6.0490 / 1000 * pow(freq, 2) - 1.5707 / 100000 * pow(freq, 3) + 3.7572 / 10000000 * pow(freq, 4);
pointer = constants;
return pointer;
}
int _tmain(int argc, _TCHAR* argv[])
{
double * constants;
//Determine constants based on freq (see manual pump)
double freq;
cin >> freq;
double head;
cin >> head;
constants = Calc_constants(freq);
cout << constants[0] << endl << constants[1] << endl << constants << endl;
cout << NewtonRaphson(head, 0, 0.001, constants) << endl;
cin >> freq;
return 0;
}
The function Calc_constants returns a pointer to an array of calculated values.
So far so good.
The function NewtonRaphson takes the pointer to this array as a parameter.
When dereferencing this pointer in this function it returns different results for constants[0] and constants[1]. I find this very strange, because the address the pointer is 'pointing' to is the same.
To clarify this is the output (cout):
-0.09505
2.6008
OOD6F604
00D6F604
-9.25596e+0.61
-9.25596e+0.61
-1.08038e-0.62
double * Calc_constants(double freq)
{
double * pointer;
double constants[6];
Calc_constants allocates memory for this array on its stack, not on heap.
When this function returns, this block of memory may be allocated for some other purpose, hence is not supposed to be accessed outside of this function.
Because of this, when pointer is returned, and used later, it leads to unpredictable results.
constants array needs to be allocated either in main or on heap so its lifetime is long enough for this kind of usage.
In this while loop condition,
while (abs(Calc_H(Q_iter, Head, constants)) > max_error || iter_counter > 1000)
I guess, it should be iter_counter < 1000.
There's not much C++ in your code. First of all, let's remove the non-standard stuff:
#include "stdafx.h"
#include "math.h"
#include <iostream>
Should become:
#include <math.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
Should become:
int main()
Then there are C-style arrays all over the place. You don't want to do that. Use std::array or std::vector and the problem will disappear all by itself.
Here is an example with std::vector:
#include <math.h>
#include <iostream>
#include <vector>
double Calc_H(double Q, double Head, std::vector<double> const& constants)
{
return (constants[0] * pow(Q, 4) + constants[1] * pow(Q, 3) + constants[2] * pow(Q, 2) + constants[3] * Q + constants[4] - Head);
}
double Calc_dH(double Q, std::vector<double> const& constants)
{
return (4 * constants[0] * pow(Q, 3) + 3 * constants[1] * pow(Q, 2) + 2 * constants[2] * Q + constants[3]);
}
double NewtonRaphson(double Head, double first_guess, double max_error, std::vector<double> const& constants)
{
double Q_iter = first_guess;
int iter_counter = 1;
std::cout << constants.data() << std::endl << constants[0] << std::endl << constants[1] << std::endl;
while (abs(Calc_H(Q_iter, Head, constants)) > max_error && iter_counter < 1000)
{
Q_iter = Q_iter - Calc_H(Q_iter, Head, constants) / Calc_dH(Q_iter, constants);
iter_counter++;
}
return Q_iter;
}
std::vector<double> Calc_constants(double freq)
{
std::vector<double> constants(6);
constants[0] = -1.2363 + 2.3490 / 10 * freq - 1.3754 / 100 * pow(freq, 2) + 2.9027 / 10000 * pow(freq, 3) - 2.0004 / 1000000 * pow(freq, 4);
constants[1] = 1.9547 - 4.5413 / 10 * freq + 3.5392 / 100 * pow(freq, 2) - 8.1716 / 10000 * pow(freq, 3) + 5.9227 / 1000000 * pow(freq, 4);
constants[2] = -5.3522 - 4.5413 / 10 * freq - 1.3311 / 100 * pow(freq, 2) + 4.8787 / 10000 * pow(freq, 3) - 4.8767 / 1000000 * pow(freq, 4);
constants[3] = 3.8894 / 100 + 3.5888 / 10 * freq + 1.0024 / 100 * pow(freq, 2) - 5.6565 / 10000 * pow(freq, 3) + 7.5172 / 1000000 * pow(freq, 4);
constants[4] = -8.1649 + 5.4525 / 10 * freq - 3.2415 / 100 * pow(freq, 2) + 8.9033 / 10000 * pow(freq, 3) - 9.0927 / 1000000 * pow(freq, 4);
constants[5] = 2.1180 / 10 + 5.0018 / 100 * freq + 6.0490 / 1000 * pow(freq, 2) - 1.5707 / 100000 * pow(freq, 3) + 3.7572 / 10000000 * pow(freq, 4);
return constants;
}
int main()
{
//Determine constants based on freq (see manual pump)
double freq;
std::cin >> freq;
double head;
std::cin >> head;
std::vector<double> constants = Calc_constants(freq);
std::cout << constants[0] << std::endl << constants[1] << std::endl << constants.data() << std::endl;
std::cout << NewtonRaphson(head, 0, 0.001, constants) << std::endl;
std::cin >> freq;
return 0;
}
(I've also modified the while loop to what I guess is what you intended.)
As you can see, element access has the same syntax as C arrays. A pointer to the data encapsulated by the std::vector is obtained with data(). I've added this since your original code printed the address of the array; you will rarely need data() in your real code for this kind of application.
Now, as far as your original code is concerned:
double * Calc_constants(double freq)
{
double * pointer;
double constants[6];
// ...
pointer = constants;
return pointer;
}
This simply produces undefined behaviour. constants is a local variable. The six elements you create here are destroyed when the function returns, yet you keep a pointer to them. The C++ language makes no guarantees as to what will happen, should you try to dereference that pointer later on (as you do). With some luck, the program would have crashed immediately, showing you that there is a serious error, rather than generating nonsense output.
You were a bit unlucky as well not to get a compiler warning for this. Had you not used the redundant pointer variable, then you might have received a warning (at least with VC 2013).
Simple example:
double * Calc_constants()
{
double constants[6];
return constants;
}
int main()
{
double* ptr = Calc_constants();
}
VC 2013 warning:
warning C4172: returning address of local variable or temporary
With std::vector, the data is allocated internally such that you can safely return objects. You can use standard container objects as safely as simple ints, without raw-pointer complexities sprinkled all over your code.