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);
}
Related
A real world third party API takes a parameter of type fraction which is a struct of an int numerator and denominator. The value that I need to pass is known to me as a decimal string that is converted to a double.
The range of possible values are, let's say 10K to 300M but if there is a fraction part after the decimal point, it's significant.
I have here code for two approximation approaches, one uses the extended euclidean algorithm while the other is brute-force. Both methods find a rational approximation using int types for a given double.
The brute-force is of course the more accurate of the two and is actually faster when the converted numbers are large. My questions is, can I say anything clever about the quality of the approximation using the euclidean algorithm.
More formally, can I put a bound on the approximation using the euclidean algorithm vs. the approximation of the brute-force algorithm (which I believe to be optimal).
An example for a bound:
If the error of the optimal approximation is r, then the euclidean algorithm approximation would produce an error that is less than 2*r.
(I'm not claiming this is the bound and I certainly can't prove it, it's just an example for what a good bound may look like).
Here's the code an a test program:
#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>
#include <chrono>
#include <random>
// extended euclidian algorithm
// finds the coefficients that produce the gcd
// in u, we store m,n the coefficients that produce m*a - n*b == gcd.
// in v, we store m,n the coefficients that produce m*a - n*b == 0.
// breaks early if the coefficients become larger than INT_MAX
int gcd_e(uint64_t a, int b, int u[2], int v[2])
{
auto w = lldiv(a, b);
// u[0] * a' - u[1] * b' == a
// v[0] * a' - v[1] * b' == b
// a - w.quot * b == w.rem
// (u[0] * a' - u[1] * b') - w.quot * (v[0] * a' - v[1] * b') == w.rem
// (u[0] - w.quot * v[0]) * a' - u[1] * b' + w.quot * v[1] * b' == w.rem
// (u[0] - w.quot * v[0]) * a' + (w.quot * v[1] - u[1]) * b' == w.rem
// (u[0] - w.quot * v[0]) * a' - (u[1] - w.quot * v[1]) * b' == w.rem
auto m = u[0] - w.quot * v[0];
auto n = u[1] - w.quot * v[1];
u[0] = v[0];
u[1] = v[1];
constexpr auto L = std::numeric_limits<int>::max();
if (m > L || n > L)
throw 0; // break early
if (m < -L || n < -L)
throw 0; // break early
v[0] = int(m);
v[1] = int(n);
if (w.rem == 0)
return b;
return gcd_e(b, int(w.rem), u, v);
}
inline double helper_pre(double d, bool* negative, bool* inverse)
{
bool v = (d < 0);
*negative = v;
if (v)
d = -d;
v = (d < 1);
*inverse = v;
if (v)
d = 1 / d;
return d;
}
inline void helper_post(int* m, int* n, bool negative, bool inverse)
{
if (inverse)
std::swap(*n, *m);
if (negative)
*n = -(*n);
}
// gets a rational approximation for double d
// numerator is stored in n
// denominator is stored in m
void approx(double d, int* n, int *m)
{
int u[] = { 1, 0 }; // 1*a - 0*b == a
int v[] = { 0, -1 }; // 0*a - (-1)*b == b
bool negative, inverse;
d = helper_pre(d, &negative, &inverse);
constexpr int q = 1 << 30;
auto round_d = std::round(d);
if (d == round_d)
{
// nothing to do, it's an integer.
v[1] = int(d);
v[0] = 1;
}
else try
{
uint64_t k = uint64_t(std::round(d*q));
gcd_e(k, q, u, v);
}
catch (...)
{
// OK if we got here.
// int limits
}
// get the approximate numerator and denominator
auto nn = v[1];
auto mm = v[0];
// make them positive
if (mm < 0)
{
mm = -mm;
nn = -nn;
}
helper_post(&mm, &nn, negative, inverse);
*m = mm;
*n = nn;
}
// helper to test a denominator
// returns the magnitude of the error
double helper_rattest(double x, int tryDenom, int* numerator)
{
double r = x * tryDenom;
double rr = std::round(r);
auto num = int(rr);
auto err = std::abs(r - rr) / tryDenom;
*numerator = num;
return err;
}
// helper to reduce the rational number
int gcd(int a, int b)
{
auto c = a % b;
if (c == 0)
return b;
return gcd(b, int(c));
}
// gets a rational approximation for double d
// numerator is stored in n
// denominator is stored in m
// uses brute force by scanning denominator range
void approx_brute(double d, int* n, int* m)
{
bool negative, inverse;
d = helper_pre(d, &negative, &inverse);
int upto = int(std::numeric_limits<int>::max() / d);
int bestNumerator;
int bestDenominator = 1;
auto bestErr = helper_rattest(d, 1, &bestNumerator);
for (int kk = 2; kk < upto; ++kk)
{
int n;
auto e = helper_rattest(d, kk, &n);
if (e < bestErr)
{
bestErr = e;
bestNumerator = n;
bestDenominator = kk;
}
if (bestErr == 0)
break;
}
// reduce, just in case
auto g = gcd(bestNumerator, bestDenominator);
bestNumerator /= g;
bestDenominator /= g;
helper_post(&bestDenominator, &bestNumerator, negative, inverse);
*n = bestNumerator;
*m = bestDenominator;
}
int main()
{
int n, m;
auto re = std::default_random_engine();
std::random_device rd;
re.seed(rd());
for (auto& u : {
std::uniform_real_distribution<double>(10000, 15000),
std::uniform_real_distribution<double>(100000, 150000),
std::uniform_real_distribution<double>(200000, 250000),
std::uniform_real_distribution<double>(400000, 450000),
std::uniform_real_distribution<double>(800000, 850000),
std::uniform_real_distribution<double>(1000000, 1500000),
std::uniform_real_distribution<double>(2000000, 2500000),
std::uniform_real_distribution<double>(4000000, 4500000),
std::uniform_real_distribution<double>(8000000, 8500000),
std::uniform_real_distribution<double>(10000000, 15000000)
})
{
auto dd = u(re);
std::cout << "approx: " << std::setprecision(14) << dd << std::endl;
auto before = std::chrono::steady_clock::now();
approx_brute(dd, &n, &m);
auto after = std::chrono::steady_clock::now();
std::cout << n << " / " << m << " dur: " << (after - before).count() << std::endl;
before = std::chrono::steady_clock::now();
approx(dd, &n, &m);
after = std::chrono::steady_clock::now();
std::cout << n << " / " << m << " dur: " << (after - before).count()
<< std::endl
<< std::endl;
}
}
Here's some sample output:
approx: 13581.807792679
374722077 / 27590 dur: 3131300
374722077 / 27590 dur: 15000
approx: 103190.31976517
263651267 / 2555 dur: 418700
263651267 / 2555 dur: 6300
approx: 223753.78683426
1726707973 / 7717 dur: 190100
1726707973 / 7717 dur: 5800
approx: 416934.79214075
1941665327 / 4657 dur: 102100
403175944 / 967 dur: 5700
approx: 824300.61241502
1088901109 / 1321 dur: 51900
1088901109 / 1321 dur: 5900
approx: 1077460.29557
1483662827 / 1377 dur: 39600
1483662827 / 1377 dur: 5600
approx: 2414781.364653
1079407270 / 447 dur: 17900
1079407270 / 447 dur: 7300
approx: 4189869.294816
1776504581 / 424 dur: 10600
1051657193 / 251 dur: 9900
approx: 8330270.2432111
308219999 / 37 dur: 5400
308219999 / 37 dur: 10300
approx: 11809264.006453
1830435921 / 155 dur: 4000
1830435921 / 155 dur: 10500
Thanks to all who commented and drew my attention to the concept of continued fractions.
According to this paper by (William F. Hammond)
There is equivalence between the euclidean algorithm and the continued fractions method.
The sub-optimal results are due to the fact that the numerator is constrained as well as the denominator so if the non brute force algorithm only produces "convergents" it means that it neglects the range of denominators between the first convergent to violate the constraints and the one just before it.
The denominators after the returned convergent and the one that follows may approximate close to the latter convergent and the difference between subsequent convergents can be shown to be:
So I suppose this would be the bound on the difference between the brute-force and the euclidean algorithm. The ratio of the error between them can be practically anything.
(can find examples of error ratios of more than 100 easily)
I hope I read everything correctly. I'm no authority on this.
#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)
#include <cmath> \\not sure if I need cmath
#include <iostream>
using namespace std;
this while loop serves to loop the " enter number of terms to approximate.
while (a != 0)
{
here is the Leibniz formula:
double c = 0.00, d = 0.00;
for (int i = 1; i <= a)
{
if (i % 2 != 0)
{
d = 1 / (1 + 2 * (i - 1));
}
else
{
d = -1 / (1 + 2 * (i - 1));
}
c = c + d;
i = i + 1
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(5);
cout << "The approximation for Leibniz's Formula is " << c << "
using "<< a <<" terms." << endl;
here is the Wallis formula:
double e = 1.00;
for (int u = 0; u<a; u++)
{
e = e * (2 * a / (2 * a - 1))*(2 * a / (2 * a + 1));
}
cout << "The approximation for Wallis' Formula is " << e << " using
"<< a <<" terms." << endl;
cout << endl;
cout << "Enter the number of terms to approximate (or zero to
quit):" << endl;
cin >> a;
}
For a=1 I am getting 1.0000 in the first formula output and 0.00000 in the second formula output
A line like this
d = 1 / (1 + 2 * (i - 1));
will use integer arithmetics to calculate the result, and then convert the int result to a double.
Change it to
d = 1.0 / (1 + 2 * (i - 1));
or even
d = 1.0 / (1.0 + 2.0 * (i - 1.0));
There are many mistakes in this code. First, comments in c++ use //, not \\.
#include <cmath> //not sure if I need cmath
You have to have two semicolons in for statements, even if you don't need loop-expression.
for (int i = 1; i <= a;)
The d will evaluate to 0 for every i that is greater than 1. You are using integer division, when you clearly want floating point division. You have to tell that to the compiler like this.
d = 1.0 / (1 + 2 * (i - 1));
When the left argument of division operator is double compiler will know, that you want to perform a floating point division. If it would be int as in your code, integer division would be performed and result converted to double.
Also in the Wallis formula you misplaced a for u, and also u parameter should start at 1, not 0. Also the integer division problem persists here.
double e = 1.00;
for (int u = 1; u<a; u++)
{
e = e * (2.0 * u / (2.0 * u - 1))*(2.0 * u / (2.0 * u + 1));
}
If you fix this all, the program starts to output valid results.
Below is my 4th order Runge-Kutta algorithm to solve a first order ODE. I am checking it against the wikipedia example found here to solve:
\frac{dx}{dt} = tan(x) + 1
Unfortunately it is out by a little bit. I have toyed around for a long while, but I can't find the error. The answer should be t = 1.1 and x = 1.33786352224364362. The below code gives t = 1.1 and x = 1.42223.
/*
This code is a 1D classical Runge-Kutta method. Compare to the Wikipedia page.
*/
#include <math.h>
#include <iostream>
#include <iomanip>
double x,t,K,K1,K2,K3,K4;
const double sixth = 1.0 / 6.0;
static double dx_dt(double t, double x){
return tan(x) + 1;
}
int main(int argc, const char * argv[]) {
/*======================================================================*/
/*===================== Runge-Kutta Method for ODE =====================*/
/*======================================================================*/
double t_initial = 1.0;// initial time
double x_initial = 1.0;// initial x position
double t_final = 1.1;// value of t wish to know x
double dt = 0.025;// time interval for updates
double halfdt = 0.5*dt;
/*======================================================================*/
while(t_initial < t_final){
/*============================ Runge-Kutta increments =================================*/
double K1 = dt*dx_dt( t_initial, x_initial );
double K2 = dt*dx_dt( t_initial + halfdt, x_initial + halfdt*K1 );
double K3 = dt*dx_dt( t_initial + halfdt, x_initial + halfdt*K2 );
double K4 = dt*dx_dt( t_initial + dt, x_initial + dt*K3 );
x_initial += sixth*(K1 + 2*(K2 + K3) + K4);
/*============================ prints =================================*/
std::cout << t_initial << std::setw(16) << x_initial << "\n";
/*============================ re-setting update conditions =================================*/
t_initial += dt;
/*======================================================================*/
}
std::cout<<"----------------------------------------------\n";
std::cout << "t = "<< t_initial << ", x = "<< x_initial << std::endl;
}/* main */
The problem is that the tableau used for your code is different than the one for the code you cited in wikipedia. The one you're using is this:
0 |
1/2 | 1/2
1/2 | 0 1/2
1 | 0 0 1
-------------------------------------
| 1/6 1/3 1/3 1/6
And the one used in wikipedia is
0 |
2/3 | 2/3
---------------------
| 1/4 3/4
Different tableaus will yield different results depending on the step-size, which is the way used to make sure that the step-size is good enough for a certain accuracy. However, when dt -> 0, then all tableaus are the same.
Besides all this, your code is wrong anyway even for RK4. The second part of the function should have halves, not 0.5*dt:
double K1 = dt*dx_dt( t_initial, x_initial );
double K2 = dt*dx_dt( t_initial + halfdt, x_initial + 0.5*K1 );
double K3 = dt*dx_dt( t_initial + halfdt, x_initial + 0.5*K2 );
double K4 = dt*dx_dt( t_initial + dt, x_initial + K3 );
You are making a rather usual mistake in trying to be overly correct and implement the two variants of the algorithm at once.
It should either be
k2 = dt*f(t+0.5*dt, x+0.5*k1)
or
k2 = f(t+0.5*dt, x+0.5*dt*k1)
the other ks accordingly.
Note that in both cases the slope fonly gets multiplied with dt once.
I think you are including one too many increments and have introduced problems by rearranging the mathematics. Try this:
#include <math.h>
#include <iostream>
#include <iomanip>
static double dx_dt(double t, double x)
{
return tan(x) + 1;
}
int main(int argc, const char * argv[])
{
double t = 1.0;
double t_end = 1.1;
double y = 1.0;
double h = 0.025;
std::cout << std::setprecision(16);
int n = static_cast<int>((t_end - t) / h);
for (int i = 0; i < n; i++)
{
double k1 = dx_dt(t, y);
double k2 = dx_dt(t + h / 2.0, y + h*k1 / 2.0);
double k3 = dx_dt(t + h / 2.0, y + h*k2 / 2.0);
double k4 = dx_dt(t + h, y + h*k3);
y += (k1 + 2 * k2 + 2 * k3 + k4) * h / 6.0;
std::cout << t << ": " << y << std::endl;
t += h;
}
std::cout << "----------------------------------------------\n";
std::cout << "t = " << t << ", x = " << y << std::endl;
std::getchar();
}
I precalculate how many times to do the iteration, this avoids a few different issues. Also as others have mentioned, the worked example on wikipedia is for a two stage variant of the algorithm.
I've taken the liberty of changing the variable names to match wikipedia. A good tip is always match the naming of your reference text until the thing works.
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.