The following code is meant to calculate 7 terms: tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap (only the calculation of tpos1 and tpos2 is shown here), and determine the entry that satisfies the condition of being the smallest positive non-zero entry.
int hitb;
double PCLx = 2.936728;
double PCLz = -0.016691;
double PDCx = 0.102796;
double PDCz = 0.994702;
double q = 0.002344;
double s = 0.0266;
double v = 0.0744;
double a = -q * PDCx * PDCx;
double b = s * PDCx - 2 * q*PCLx*PDCx - PDCz;
double c = -1.0*(PCLz + q * pow(PCLx, 2) - s * PCLx + v);
double d = b * b - 4 * a*c;
if (d >= 0.0f) // only take solution if t real
{
tpos1 = (-b + sqrt(d)) / (2 * a);
tpos2 = (-b - sqrt(d)) / (2 * a);
}
printf("\n %f %f %f %f %f %f %f", tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap);
yielding the result:
0.000000 0.000000 -40326.381162 -0.156221 -40105.748386 0.000194 0.016780
It is seen that the expected result should be smallest = tpos2 = 0.000194.
double smallest = -1.0;
double tlist[7] = { tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap };
const int size = sizeof(tlist) / sizeof(int);
for (int i = 0; i < size; i++)
{
if (tlist[i] > EPSILON && (smallest == -1.0 || tlist[i] < smallest))
{
smallest = tlist[i];
}
}
printf("\n %f", smallest);
The output for smallest = 0.000192, thus smallest != tpos2 != 0.00194. Why is there this small change in value for the selected smallest entry?
The result of smallest will be fed to the following code:
if (smallest == tneg1 || smallest == tneg2)
{
hitb = 1;
}
else if (smallest == tpos1 || smallest == tpos2)
{
hitb = 2;
}
else if (smallest == tcappos)
{
hitb = 3;
}
else if (smallest == tcapneg)
{
hitb = 4;
}
else if (smallest == tzcap)
{
hitb = 5;
}
In this case, we should satisfy the condition to write hitb = 2, however this is failing due to the inequality above.
Your array double tlist[7] is in double with 7 elements. sizeof(double) is 8, so sizeof(tlist) is 8*7 = 56. While sizeof(int) is 4, so your size = sizeof(tlist) / sizeof(int) is 56/4 = 14. Your loop goes beyond number of elements in the array. It counts 7 more double values after the array in memory, because the array name is used as a pointer.
Here is my code to verify the above nanalysis
#include <iostream>
using namespace std;
int main()
{
double da[7] = {0.0, 0.0, -40326.381162, -0.156221, -40105.748386, 0.000194, 0.016780};
const int sda = sizeof(da);
const int sin = sizeof(int);
const int siz = sda/sin;
cout << "sda:" << sda << " sin:" << sin << " siz:" << siz << endl;
for( int i=0; i<siz; i++ ) {
cout << "da[" << i << "] = " << da[i] << endl;
}
return 0;
}
Here is the output
sda:56 sin:4 siz:14
da[0] = 0
da[1] = 0
da[2] = -40326.4
da[3] = -0.156221
da[4] = -40105.7
da[5] = 0.000194
da[6] = 0.01678
da[7] = 2.07324e-317
da[8] = 8.48798e-314
da[9] = 1.9098e-313
da[10] = 0
da[11] = 1.31616e-312
da[12] = 0
da[13] = 6.95332e-310
The correct code is
size = sizeof(tlist) / sizeof(double);
Use the following option for GCC to report runtime error in this case
g++ -fsanitize=bounds -o main.e main.cpp
Probably you never iterate over the last elements of the array: you calculate the size as sizeof(double*) / sizeof(int) which is not true. Just use std::vector type for an array and iterate over it using iterator types:
std::vector<double>tlist = ...
for(auto i = tlist.begin(); i != tlist.end(); i++)
{
double v = (*i);
/* ... */
}
Also you should thoroughly check the logic of your condition: is EPSILON positive?
Related
Using the formula in the pic, I need to write a program that allows the user to calculate sin(x), cos(x), tan(x). The user should enter the angle in degrees, and then the program should transform it into radians before performing the three requested calculations. For each requested calculation (i.e., sin(x), cos(x), tan(x)), I only need to calculate the first 15 terms of the series.
The problem seems to be in the arrays of the last block in the code, it keeps returning wrong results of the tan(x) series; how can I fix it?
#include <iostream>
using namespace std;
//create a function to convert angles from degrees to radian
double convertToRadian(double deg)
{ //formula : radian = (degree * pi)/180
const double pi = 3.14159265359; //declaring pi's value as a constant
return (deg * (pi / 180)); //returning the radian value
}
//create a function to calculate the exponent/power
double power(double base, unsigned int exp)
{
double result = 1;
for(int i = 0; i < exp; i++){
result = result * base;
}
return result;
}
//create a function to get the factorial of a value
double factorial(int fac)
{
if(fac > 1)
return fac * factorial(fac - 1);
else
return 1;
}
//create a function to print out arrays as we will use it to print the terms in the series
void printTerms(double terms[15])
{ for (int i = 0; i < 15; i++)
{
cout<<terms[i]<<endl;
}
}
int main()
{
double degree; //declare the variables used in the program
double valueOfCos, valueOfSin, valueOfTan; //declare variables for terms of each function
cout << "Enter angle (x) in degrees: " << endl; //prompt for user to enter angle in deg
cin >> degree;
double radian = convertToRadian(degree); //first, converting from degrees to radian
//make an array for the first 15 terms of cos(x):
double cos[15];
//make a loop to insert values in the array
for (int n = 0; n < 15; n++)
{ //type the maclaurin series formula for cos(x):
valueOfCos = (( power(-1 , n)) / (factorial(2*n))) * (power(radian, (2*n)));
cos[n] = valueOfCos;
}
//print out the first 15 terms of cos(x) in the maclaurin series:
cout << "cos(x)= ";
printTerms (cos);
//make an array for the first 15 terms of sin(x):
double sin[15];
for (int n = 0; n < 15; n++)
{
valueOfSin = ((power(-1 , n)) / (factorial((2*n + 1)))) * (power(radian, (2*n + 1)));
sin[n] = valueOfSin;
}
cout << "sin(x)= ";
printTerms (sin);
double tan[15];
for (int n = 0; n < 15; n++)
{ double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730),
(7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730),
(8553103/6),(-23749461029/870),(8615841276005/14322) };
for (int i = 0; i < 15; i++)
{
double firstNum = 0, secondNum = 0 , thirdNum = 0 , denominator = 0;
firstNum = power(-1 , n);
secondNum = power(2 , 2*n + 2);
thirdNum = ((secondNum) - 1);
denominator = factorial(2*n + 2);
valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[i])) / denominator) *
(power(radian, 2*n + 1));
tan [n] = valueOfTan;
}
}
cout << "tan(x)= ";
printTerms (tan);
return 0;
}
This loop : for (int n = 0; n < 15; n++) is not running or entire expression. You'll need to correct something like this :
double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730),(7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730),(8553103/6),(-23749461029/870),(8615841276005/14322) };
for (int n = 0; n < 15; n++){
double firstNum = 0, secondNum = 0 , thirdNum = 0 , denominator = 0;
firstNum = power(-1 , n);
secondNum = power(2 , 2*n + 2);
thirdNum = ((secondNum) - 1);
denominator = factorial(2*n + 2);
valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[n])) / denominator) * (power(radian, 2*n + 1));
tan [n] = valueOfTan;
}
}
You are incorrectly calculating the tan value.
In valueOfTan = ((firstNum * secondNum * thirdNum * (bernoulli[i])) / denominator) * (power(radian, 2 * n + 1));
Instead of bernoulli[i], you need to have bernoulli[2*i+2] as per the formulae.
And one more suggestion please pull the double bernoulli[15] = {(1/6), (-1/30),(1/42), (-1/30), (5/66), (-691/2730), (7/6), (-3617/510), (43867/798), (-174611/330), (854513/138), (-236364091/2730), (8553103/6),(-23749461029/870),(8615841276005/14322) array initialization out of the for loop, as it's constant you don't need to initialize it every time unnecessarily. It will increase your code runtime
I wanna use monte-carlo integration method, and my code is below. As u can see i determined the interval integration but the result is wrong ! Whats wrong with this code ?
any help will be appreciated .
#include <iostream>
#include <math.h>
#include <stdlib.h>
#define N 500
using namespace std;
double Func(double x) { return pow(x, 2) + 1; }
double Monte_Carlo(double Func(double), double xmin, double xmax, double ymin,
double ymax)
{
int acc = 0;
int tot = 0;
for (int count = 0; count < N; count++)
{
double x0 = (double)rand() / 4 + (-2);
double y0 = (double)rand() / 4 + 0;
float x = x0 / (float)RAND_MAX;
float y = y0 / (float)RAND_MAX;
cout << x << endl;
if (y <= Func(x))
acc++;
tot++;
// cout << "Dgage" << tot << '\t' << acc << endl;
}
double Coeff = acc / N;
return (xmax - xmin) * (1.2 * Func(xmax)) * Coeff;
}
int main()
{
cout << "Integral value is: " << Monte_Carlo(Func, -2, 2, 0, 4) << endl;
system("pause");
return 0;
}
The Monte_Carlo function is making things more complicated then they need to be. For integrating a 1-dimensional function, all we have to do is sample the value of the function a bunch of times within the region we're integrating over:
#include <random>
double Monte_Carlo(double Func(double), double xmin, double xmax, int N)
{
// This is the distribution we're using to generate inputs
auto x_dist = std::uniform_real_distribution<>(xmin, xmax);
// This is the random number generator itself
auto rng = std::default_random_engine();
// Calculate the total of N random samples
double total = 0.0;
for(int i = 0; i < N; i++) {
double x = x_dist(rng); // Generate a value
total += Func(x);
}
// Return the size of the interval times the total,
// divided by the number of samples
return (xmax - xmin) * total / N;
}
If we run this code with N = 1000, we get an integral value of 9.20569, which is pretty close to the exact answer (9.33333...).
// It's much more efficent to use x*x instead of pow
double func(double x) { return x * x + 1; }
int main()
{
cout << "Integral value is: " << Monte_Carlo(func, -2, 2, 1000) << endl;
getchar(); // Pause until the user presses enter
return 0;
}
We can also try multiple values of N, to have the program show how it converges. The following program calculates the integral with N being powers of 2 from 0 to 30
#include <iostream>
#include <cmath>
#include <random>
using namespace std;
double func(double x) { return x*x + 1; }
double Monte_Carlo(double Func(double), double xmin, double xmax, int N) {
auto x_dist = std::uniform_real_distribution<>(xmin, xmax);
auto rng = std::default_random_engine();
double total = 0.0;
for(int i = 0; i < N; i++) {
double x = x_dist(rng); // Generate a value
total += Func(x);
}
return (xmax - xmin) * total / N;
}
int main() {
int N = 1;
for(int i = 0; i < 31; i++) {
std::cout << "N = " << N << "\t\tintegral = " << Monte_Carlo(func, -2, 2, N) << endl;
N *= 2; // Double N
}
}
The output shows that the monte carlo method does actually converge:
N = 1 integral = 12.6889
N = 2 integral = 8.39917
N = 4 integral = 7.97521
N = 8 integral = 9.24233
N = 16 integral = 9.75632
N = 32 integral = 9.87064
N = 64 integral = 9.46945
N = 128 integral = 9.27281
N = 256 integral = 9.27395
N = 512 integral = 9.17546
N = 1024 integral = 9.19097
N = 2048 integral = 9.26203
N = 4096 integral = 9.37979
N = 8192 integral = 9.36167
N = 16384 integral = 9.28918
N = 32768 integral = 9.29766
N = 65536 integral = 9.31101
N = 131072 integral = 9.3227
N = 262144 integral = 9.32588
N = 524288 integral = 9.32805
N = 1048576 integral = 9.32726
N = 2097152 integral = 9.32722
N = 4194304 integral = 9.331
N = 8388608 integral = 9.33082
N = 16777216 integral = 9.33174
N = 33554432 integral = 9.33164
N = 67108864 integral = 9.33303
N = 134217728 integral = 9.33283
N = 268435456 integral = 9.33327
N = 536870912 integral = 9.33325
N = 1073741824 integral = 9.33333
I copied the code of Moro's Inverse Cumulative function of Normal distribution, where I added an extra error handling to deal with the input that is out of range (0,1). When I tested the code with all valid inputs, the speed is slowed down about 25% (6ns vs 8ns). I'm quite curious that why even no execution the throw exception still slow down the performance?
Code of Inverse function:
double Inverse(double u)
{
double a[4] = {
2.50662823884,
-18.61500062529,
41.39119773534,
-25.44106049637 };
double b[4] = {
-8.47351093090,
23.08336743743,
-21.06224101826,
3.13082909833 };
double c[9] = {
0.3374754822726147,
0.9761690190917186,
0.1607979714918209,
0.0276438810333863,
0.0038405729373609,
0.0003951896511919,
0.0000321767881768,
0.0000002888167364,
0.0000003960315187 };
// Assert( 0 < u && u < 1 );
if (u >= 1 || u <= 0){
throw std::invalid_argument("Input out of range.");
}
/*return the inverse of cumulative normal distribution fonction*/
double x, r;
x = u - 0.5;
if (fabs(x)<0.42) {
r = x*x;
r = x*(((a[3] * r + a[2])*r + a[1])*r + a[0]) / ((((b[3] * r + b[2])*r + b[1])*r + b[0])*r + 1.0);
return(r);
}
r = u;
if (x>0.0) r = 1 - u;
r = log(-log(r));
r = c[0] + r*(c[1] + r*(c[2] + r*(c[3] + r*(c[4] + r*(c[5] + r*(c[6] + r*(c[7] + r*c[8])))))));
if (x<0.0) r = -r;
return(r);
}
And the test code is
int m = 1000000, n = 1000;
double z, p, dz = 1.0 / double(m) / double(n);
clock_t t1, t2;
t1 = clock();
z = 1e-9;
p = 0.0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
z += dz * 0.999;
p = Inverse(z);
}
}
t2 = clock();
cout << z << '\t' << p << endl;
cout << "Inverse" << '\t' << float(t2 - t1) / CLOCKS_PER_SEC << endl;
Even if the exception is not executed, the computer still has to check the value of the variable 'u' in the condition, which takes time.
This is a problem I have been struggling for a week, coming back just to give up after wasted hours...
I am supposed to find coefficents for the following Laguerre polynomial:
P0(x) = 1
P1(x) = 1 - x
Pn(x) = ((2n - 1 - x) / n) * P(n-1) - ((n - 1) / n) * P(n-2)
I believe there is an error in my implementation, because for some reason the coefficents I get seem way too big. This is the output this program generates:
a1 = -190.234
a2 = -295.833
a3 = 378.283
a4 = -939.537
a5 = 774.861
a6 = -400.612
Description of code (given below):
If you scroll the code down a little to the part where I declare array, you'll find given x's and y's.
The function polynomial just fills an array with values of said polynomial for certain x. It's a recursive function. I believe it works well, because I have checked the output values.
The gauss function finds coefficents by performing Gaussian elimination on output array. I think this is where the problems begin. I am wondering, if there's a mistake in this code or perhaps my method of veryfying results is bad? I am trying to verify them like that:
-190.234 * 1.5 ^ 5 - 295.833 * 1.5 ^ 4 ... - 400.612 = -3017,817625 =/= 2
Code:
#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double polynomial(int i, int j, double **tab)
{
double n = i;
double **array = tab;
double x = array[j][0];
if (i == 0) {
return 1;
} else if (i == 1) {
return 1 - x;
} else {
double minusone = polynomial(i - 1, j, array);
double minustwo = polynomial(i - 2, j, array);
double result = (((2.0 * n) - 1 - x) / n) * minusone - ((n - 1.0) / n) * minustwo;
return result;
}
}
int gauss(int n, double tab[6][7], double results[7])
{
double multiplier, divider;
for (int m = 0; m <= n; m++)
{
for (int i = m + 1; i <= n; i++)
{
multiplier = tab[i][m];
divider = tab[m][m];
if (divider == 0) {
return 1;
}
for (int j = m; j <= n; j++)
{
if (i == n) {
break;
}
tab[i][j] = (tab[m][j] * multiplier / divider) - tab[i][j];
}
for (int j = m; j <= n; j++) {
tab[i - 1][j] = tab[i - 1][j] / divider;
}
}
}
double s = 0;
results[n - 1] = tab[n - 1][n];
int y = 0;
for (int i = n-2; i >= 0; i--)
{
s = 0;
y++;
for (int x = 0; x < n; x++)
{
s = s + (tab[i][n - 1 - x] * results[n-(x + 1)]);
if (y == x + 1) {
break;
}
}
results[i] = tab[i][n] - s;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int num;
double **array;
array = new double*[5];
for (int i = 0; i <= 5; i++)
{
array[i] = new double[2];
}
//i 0 1 2 3 4 5
array[0][0] = 1.5; //xi 1.5 2 2.5 3.5 3.8 4.1
array[0][1] = 2; //yi 2 5 -1 0.5 3 7
array[1][0] = 2;
array[1][1] = 5;
array[2][0] = 2.5;
array[2][1] = -1;
array[3][0] = 3.5;
array[3][1] = 0.5;
array[4][0] = 3.8;
array[4][1] = 3;
array[5][0] = 4.1;
array[5][1] = 7;
double W[6][7]; //n + 1
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 5; j++)
{
W[i][j] = polynomial(j, i, array);
}
W[i][6] = array[i][1];
}
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 6; j++)
{
cout << W[i][j] << "\t";
}
cout << endl;
}
double results[6];
gauss(6, W, results);
for (int i = 0; i < 6; i++) {
cout << "a" << i + 1 << " = " << results[i] << endl;
}
_getch();
return 0;
}
I believe your interpretation of the recursive polynomial generation either needs revising or is a bit too clever for me.
given P[0][5] = {1,0,0,0,0,...}; P[1][5]={1,-1,0,0,0,...};
then P[2] is a*P[0] + convolution(P[1], { c, d });
where a = -((n - 1) / n)
c = (2n - 1)/n and d= - 1/n
This can be generalized: P[n] == a*P[n-2] + conv(P[n-1], { c,d });
In every step there is involved a polynomial multiplication with (c + d*x), which increases the degree by one (just by one...) and adding to P[n-1] multiplied with a scalar a.
Then most likely the interpolation factor x is in range [0..1].
(convolution means, that you should implement polynomial multiplication, which luckily is easy...)
[a,b,c,d]
* [e,f]
------------------
af,bf,cf,df +
ae,be,ce,de, 0 +
--------------------------
(= coefficients of the final polynomial)
The definition of P1(x) = x - 1 is not implemented as stated. You have 1 - x in the computation.
I did not look any further.
I was reading through How can I write a power function myself? and the answer given by dan04 caught my attention mainly because I am not sure about the answer given by fortran, but I took that and implemented this:
#include <iostream>
using namespace std;
float pow(float base, float ex){
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// even exponenet
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main(){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ".5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ",2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ",3) = " << pow(ii, 3) << endl;
}
}
though I am not sure if I translated this right because all of the calls giving .5 as the exponent return 0. In the answer it states that it might need a log2(x) based on a^b = 2^(b * log2(a)), but I am unsure about putting that in as I am unsure where to put it, or if I am even thinking about this right.
NOTE: I know that this might be defined in a math library, but I don't need all the added expense of an entire math library for a few functions.
EDIT: does anyone know a floating-point implementation for fractional exponents? (I have seen a double implementation, but that was using a trick with registers, and I need floating-point, and adding a library just to do a trick I would be better off just including the math library)
I have looked at this paper here which describes how to approximate the exponential function for double precision. After a little research on Wikipedia about single precision floating point representation I have worked out the equivalent algorithms. They only implemented the exp function, so I found an inverse function for the log and then simply did
POW(a, b) = EXP(LOG(a) * b).
compiling this gcc4.6.2 yields a pow function almost 4 times faster than the standard library's implementation (compiling with O2).
Note: the code for EXP is copied almost verbatim from the paper I read and the LOG function is copied from here.
Here is the relevant code:
#define EXP_A 184
#define EXP_C 16249
float EXP(float y)
{
union
{
float d;
struct
{
#ifdef LITTLE_ENDIAN
short j, i;
#else
short i, j;
#endif
} n;
} eco;
eco.n.i = EXP_A*(y) + (EXP_C);
eco.n.j = 0;
return eco.d;
}
float LOG(float y)
{
int * nTemp = (int*)&y;
y = (*nTemp) >> 16;
return (y - EXP_C) / EXP_A;
}
float POW(float b, float p)
{
return EXP(LOG(b) * p);
}
There is still some optimization you can do here, or perhaps that is good enough.
This is a rough approximation but if you would have been satisfied with the errors introduced using the double representation, I imagine this will be satisfactory.
I think the algorithm you're looking for could be 'nth root'. With an initial guess of 1 (for k == 0):
#include <iostream>
using namespace std;
float pow(float base, float ex);
float nth_root(float A, int n) {
const int K = 6;
float x[K] = {1};
for (int k = 0; k < K - 1; k++)
x[k + 1] = (1.0 / n) * ((n - 1) * x[k] + A / pow(x[k], n - 1));
return x[K-1];
}
float pow(float base, float ex){
if (base == 0)
return 0;
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// fractional exponent
}else if (ex > 0 && ex < 1){
return nth_root(base, 1/ex);
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main_pow(int, char **){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ", .5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ", 2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ", 3) = " << pow(ii, 3) << endl;
}
return 0;
}
test:
pow(0, .5) = 0.03125
pow(0, 2) = 0
pow(0, 3) = 0
pow(1, .5) = 1
pow(1, 2) = 1
pow(1, 3) = 1
pow(2, .5) = 1.41421
pow(2, 2) = 4
pow(2, 3) = 8
pow(3, .5) = 1.73205
pow(3, 2) = 9
pow(3, 3) = 27
pow(4, .5) = 2
pow(4, 2) = 16
pow(4, 3) = 64
pow(5, .5) = 2.23607
pow(5, 2) = 25
pow(5, 3) = 125
pow(6, .5) = 2.44949
pow(6, 2) = 36
pow(6, 3) = 216
pow(7, .5) = 2.64575
pow(7, 2) = 49
pow(7, 3) = 343
pow(8, .5) = 2.82843
pow(8, 2) = 64
pow(8, 3) = 512
pow(9, .5) = 3
pow(9, 2) = 81
pow(9, 3) = 729
I think that you could try to solve it by using the Taylor's series,
check this.
http://en.wikipedia.org/wiki/Taylor_series
With the Taylor's series you can solve any difficult to solve calculation such as 3^3.8 by using the already known results such as 3^4. In this case you have
3^4 = 81 so
3^3.8 = 81 + 3.8*3( 3.8 - 4) +..+.. and so on depend on how big is your n you will get the closer solution of your problem.
I and my friend faced similar problem while we're on an OpenGL project and math.h didn't suffice in some cases. Our instructor also had the same problem and he told us to seperate power to integer and floating parts. For example, if you are to calculate x^11.5 you may calculate sqrt(x^115, 10) which may result more accurate result.
Reworked on #capellic answer, so that nth_root works with bigger values as well.
Without the limitation of an array that is allocated for no reason:
#include <iostream>
float pow(float base, float ex);
inline float fabs(float a) {
return a > 0 ? a : -a;
}
float nth_root(float A, int n, unsigned max_iterations = 500, float epsilon = std::numeric_limits<float>::epsilon()) {
if (n < 0)
throw "Invalid value";
if (n == 1 || A == 0)
return A;
float old_value = 1;
float value;
for (int k = 0; k < max_iterations; k++) {
value = (1.0 / n) * ((n - 1) * old_value + A / pow(old_value, n - 1));
if (fabs(old_value - value) < epsilon)
return value;
old_value = value;
}
return value;
}
float pow(float base, float ex) {
if (base == 0)
return 0;
if (ex == 0){
// power of 0
return 1;
} else if( ex < 0) {
// negative exponent
return 1 / pow(base, -ex);
} else if (ex > 0 && ex < 1) {
// fractional exponent
return nth_root(base, 1/ex);
} else if ((int)ex % 2 == 0) {
// even exponent
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
} else {
// integer exponent
return base * pow(base, ex - 1);
}
}
int main () {
for (int i = 0; i <= 128; i++) {
std::cout << "pow(" << i << ", .5) = " << pow(i, .5) << std::endl;
std::cout << "pow(" << i << ", .3) = " << pow(i, .3) << std::endl;
std::cout << "pow(" << i << ", 2) = " << pow(i, 2) << std::endl;
std::cout << "pow(" << i << ", 3) = " << pow(i, 3) << std::endl;
}
std::cout << "pow(" << 74088 << ", .3) = " << pow(74088, .3) << std::endl;
return 0;
}
This solution of MINE will be accepted upto O(n) time complexity
utpo input less then 2^30 or 10^8
IT will not accept more then these inputs
It WILL GIVE TIME LIMIT EXCEED warning
but easy understandable solution
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// static is important here
// other wise it will store same values while multiplying
double p = x;
double ans;
// as we multiple p it will multiply it with q which has the
//previous value of this ans latter we will update the q
// so that q has fresh value for further test cases here
static double q=1; // important
if(n==0){ ans = q; q=1; return ans;}
if(n>0)
{
p *= q;
// stored value got multiply by p
q=p;
// and again updated to q
p=x;
//to update the value to the same value of that number
// cout<<q<<" ";
recursive(p,n-1);
}
return ans;
}
class Solution {
public:
double myPow(double x, int n) {
// double q=x;double N=n;
// return pow(q,N);
// when both sides are double this function works
if(n==0)return 1;
x = recursive(x,abs(n));
if(n<0) return double(1/x);
// else
return x;
}
};
For More help you may try
LEETCODE QUESTION NUMBER 50
**NOW the Second most optimize code pow(x,n) **
logic is that we have to solve it in O(logN) so we devide the n by 2
when we have even power n=4 , 4/2 is 2 means we have to just square it (22)(22)
but when we have odd value of power like n=5, 5/2 here we have square it to get
also the the number itself to it like (22)(2*2)*2 to get 2^5 = 32
HOPE YOU UNDERSTAND FOR MORE YOU CAN VISIT
POW(x,n) question on leetcode
below the optimized code and above code was for O(n) only
*
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// recursive calls will return the whole value of the program at every calls
if(n==0){return 1;}
// 1 is multiplied when the last value we get as we don't have to multiply further
double store;
store = recursive(x,n/2);
// call the function after the base condtion you have given to it here
if(n%2==0)return store*store;
else
{
return store*store*x;
// odd power we have the perfect square multiply the value;
}
}
// main function or the function for indirect call to recursive function
double myPow(double x, int n) {
if(n==0)return 1;
x = recursive(x,abs(n));
// for negatives powers
if(n<0) return double(1/x);
// else for positves
return x;
}