Can I replace the built-in pow function using this custom function? - c

I'm trying to write a power function in c without calling pow().
double power (double X, int Y)
{
int i;
double value = 1;
for (i = 0; i < Y; i++)
value *= X;
return value;
}
My question is, is there any reason you can see that this function would not work properly with any given test values? I am trying to cover all input possibilities.
-Thanks

This function is inadequate for several reasons:
It's buggy. Notice that value is declared as an int rather than a double, which means that if you try to compute power(1.5, 1), you'll get back 1 rather than 1.5. In fact, it will be wrong on almost all inputs.
It doesn't handle negative exponents. Try computing power(2, -1). The correct answer is 0.5, but your function (after fixing the int bug noted above) will return 1 rather than 0.5. You can fix this pretty easily (you could, for example, compute power(2, 1) and then take the reciprocal), but it's troublesome as currently written.
It's slow. Most exponentiation, when the power is an integer, is computed using an algorithm called exponentiation by squaring, which is considerably faster than your code. Exponentiation by squaring will do Θ(log Y) multiplications, compared to the Θ(Y) multiplications your code makes. It will take exponentially longer for your function to complete.
It doesn't handle fractional exponents. Try computing power(1.5, 1.5). You'll get the wrong answer because the exponent is an int, not a double. Correcting this isn't easy; search around on Stack Overflow for other questions on how to implement this properly.
It reinvents the wheel. At a fundamental level, you should ask yourself why you're rewriting a function provided to you by the language's math libraries. This can introduce bugs or inefficiencies into the program (see the earlier bullet points) and at the end of the day you haven't increased the functionality.
Hope this helps!

Your function should be like this, it will run slower than pow() which runs in O(log Y):
#include<math.h>
#define ABS(x) ((x<0)?(-x):(x))
double power (double X, int Y)
{
int i;
double value = 1;
if (Y == 0)
{
return 1.0;
}
else if (X == 0)
{
return 0.0;
}
for (i = 0; i < ABS(Y); i++)
{
value *= X;
if (value == NAN
|| value == INFINITY
|| (X > 0 && (value*X) < value)
|| (X < 0 && (value*X) > value))
{
return NAN;
}
}
if (Y < 0) return (1.0/value);
else return value;
}

Related

Alternative to ceil() and floor() to get the closest integer values, above and below of a floating point value?

I´m looking for an alternative for the ceil() and floor() functions in C, due to I am not allowed to use these in a project.
What I have build so far is a tricky back and forth way by the use of the cast operator and with that the conversion from a floating-point value (in my case a double) into an int and later as I need the closest integers, above and below the given floating-point value, to be also double values, back to double:
#include <stdio.h>
int main(void) {
double original = 124.576;
double floorint;
double ceilint;
int f;
int c;
f = (int)original; //Truncation to closest floor integer value
c = f + 1;
floorint = (double)f;
ceilint = (double)c;
printf("Original Value: %lf, Floor Int: %lf , Ceil Int: %lf", original, floorint, ceilint);
}
Output:
Original Value: 124.576000, Floor Int: 124.000000 , Ceil Int: 125.000000
For this example normally I would not need the ceil and floor integer values of c and f to be converted back to double but I need them in double in my real program. Consider that as a requirement for the task.
Although the output is giving the desired values and seems right so far, I´m still in concern if this method is really that right and appropriate or, to say it more clearly, if this method does bring any bad behavior or issue into the program or gives me a performance-loss in comparison to other alternatives, if there are any other possible alternatives.
Do you know a better alternative? And if so, why this one should be better?
Thank you very much.
Do you know a better alternative? And if so, why this one should be better?
OP'code fails:
original is already a whole number.
original is a negative like -1.5. Truncation is not floor there.
original is just outside int range.
original is not-a-number.
Alternative construction
double my_ceil(double x)
Using the cast to some integer type trick is a problem when x is outsize the integer range. So check first if x is inside range of a wide enough integer (one whose precision exceeds double). x values outside that are already whole numbers. Recommend to go for the widest integer (u)intmax_t.
Remember that a cast to an integer is a round toward 0 and not a floor. Different handling needed if x is negative/positive when code is ceil() or floor(). OP's code missed this.
I'd avoid if (x >= INTMAX_MAX) { as that involves (double) INTMAX_MAX whose rounding and then precise value is "chosen in an implementation-defined manner". Instead, I'd compare against INTMAX_MAX_P1. some_integer_MAX is a Mersenne Number and with 2's complement, ...MIN is a negated "power of 2".
#include <inttypes.h>
#define INTMAX_MAX_P1 ((INTMAX_MAX/2 + 1)*2.0)
double my_ceil(double x) {
if (x >= INTMAX_MAX_P1) {
return x;
}
if (x < INTMAX_MIN) {
return x;
}
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i < 0 || x == i) return i; // negative x is already rounded up.
return i + 1.0;
}
As x may be a not-a-number, it is more useful to reverse the compare as relational compare of a NaN is false.
double my_ceil(double x) {
if (x >= INTMAX_MIN && x < INTMAX_MAX_P1) {
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i < 0 || x == i) return i; // negative x is already rounded up.
return i + 1.0;
}
return x;
}
double my_floor(double x) {
if (x >= INTMAX_MIN && x < INTMAX_MAX_P1) {
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i > 0 || x == i) return i; // positive x is already rounded down.
return i - 1.0;
}
return x;
}
You're missing an important step: you need to check if the number is already integral, so for ceil assuming non-negative numbers (generalisation is trivial), use something like
double ceil(double f){
if (f >= LLONG_MAX){
// f will be integral unless you have a really funky platform
return f;
} else {
long long i = f;
return 0.0 + i + (f != i); // to obviate potential long long overflow
}
}
Another missing piece in the puzzle, which is covered off by my enclosing if, is to check if f is within the bounds of a long long. On common platforms if f was outside the bounds of a long long then it would be integral anyway.
Note that floor is trivial due to the fact that truncation to long long is always towards zero.

Comparing Floating Point Numbers [duplicate]

This question already has answers here:
What is the most effective way for float and double comparison?
(34 answers)
Closed 6 years ago.
Please before you think that I'm asking the same N% Question read it first and please pay Attention to it.
I'm working on a project where I have more functions which returns double and it may be possible that some of them are the same which is a good thing in my project and if is true then I need a double comparison to see if are equal.
I know that doing an equality comparison if( x == y ) is not a smart thing and we don't need to speak why, but we can check for < or > which is the part of this Question.
Does the language (standard) guarantee this, that the comparison < and > are 100%?
If yes then, the following program can be used:
#include <stdio.h>
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || x > y){
/* Are not Equal */
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
}
Does foo(x, y); get executed? BecauseX and Y should be equal here.
EDIT:
This question doesn't seek a way to compare two double, it is only the fact that should I use, or should I don't use < > instead of ==
I know that doing an equality comparison if( x == y ) is not a smart thing
This is simply not true. It may be the right thing to do or the wrong thing to do, depending on the particular problem.
if (x < y || x > y)
This has guaranteed exactly the same effect1 as
if (x != y)
and the opposite effect of
if (x == y)
When one is wrong, the other is wrong too. When one is right, the other is right as well. Writing an equality condition with < and > symbols instead of == or != doesn't suddenly make it smarter.
[1] Except maybe when one of the operands is a NaN.
some of them are the same ... and if is true then I need a double comparison to see if are equal.
OP is questioning two different ways for testing FP equality and wondering if they are the functionally alike.
Aside from maybe NaN, which is not well defined by C, (but well defined by IEEE 754), both comparisons are alike yet fail conically equivalence testing.
Consider this double code:
if (a==b) {
double ai = 1.0/a;
double bi = 1.0/b;
printf("%d\n", ai == bi);
} else {
printf("%d\n", 1);
}
Is the result always "1"? Below is an exception (mouse over to see)
Consider a=0.0; b=-0.0. Both are equal to each other, but their inverses typically are not the same. One being positive infinity, the other: negative infinity.
The question comes down to how equal do you need? Are NaN important? Using memcmp(&a, &b, sizeof a) is certainly a strong test and maybe too strong for on select systems FP numbers can have the same non-zero value, yet different encodings. If these differences are important, or maybe just the exceptional case above, is for OP to decide.
For testing if 2 different codes/functions were producing the same binary64 result, consider rating their Unit-in-the-Last-Place difference. Something like the following: compare unsigned long long ULP_diff() against 0, 1 or 2. depending on your error tolerance.
// not highly portable
#include <assert.h>
unsigned long long ULP(double x) {
union {
double d;
unsigned long long ull;
} u;
assert(sizeof(double) == sizeof(unsigned long long));
u.d = x;
if (u.ull & 0x8000000000000000) {
u.ull ^= 0x8000000000000000;
return 0x8000000000000000 - u.ull;
}
return u.ull + 0x8000000000000000;
}
unsigned long long ULP_diff(double x, double y) {
unsigned long ullx = ULP(x);
unsigned long ully = ULP(y);
if (x > y) return ullx - ully;
return ully - ullx;
}
If you want fractional number equality, you either have to use an epsilon comparison (ie. check if the numbers are close enough to one another within a specific threshold), or use some fixed-point arithmetic very carefully to avoid rounding errors.
And yes, this same question has been asked more times than necessary:
Most effective way for float and double comparison
Floating point equality and tolerances
You need to do more reading into how comparisons work, and specifically why floating point equality doesn't work. It's not an issue with the equals operator itself, as you appear to think (For arithmetic types [when no special values like NaN are involved], !(x > y || y > x) will always be the same as x == y. In fact, most compilers will optimize x < y || x > y to x != y), but rather because rounding error is a basic part of floating point operation in the first place. x == y does indeed work for floating point types, and you can do it freely. It becomes an issue after you do any arithmetic operation and then want to compare them, because it's unpredictable what the rounding error will do.
So essentially, yes. Compare equality all you want unless you are actually doing anything with the doubles. If you are just using them as an index or something of the like, there shouldn't be a problem, as long as you know you are assigning them the same value. Using boolean identities won't save you from the basic functionality of floating-point numbers.
First of all your conditional is a little off. To check for non equality you want
( x < y || y < x)
not
(x < y || y > x )
which just checks the same thing twice, meaning x < y comes back as false.
Ignoring that small issue:
Yes > and < should be 100% in that it is almost always the same as the ==. The only difference is different behavior with Nan. But it doesn't fix your problem.
Here is a really contrived example.
#include <stdio.h>
void foo(double x, double y){
printf( "OK a:%f, b:%f\n",x,y);
}
void bar(double x, double y){
printf( "BAD a:%f, b:%f\n",x,y);
}
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || y < x){
/* Are not Equal */
bar(x, y);
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
for( int i = 0; i < 1000; i++) {
y = y + 0.1;
}
x = x + 100;
if( x < y || y < x){
bar(x, y);
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
}
Here is you output (hint its BAD)
$ ./a.exe
OK a:3.140000, b:3.140000
BAD a:103.140000, b:103.140000
Best practice I know for double equality is to check there closeness within some epsilon,
eps = 0.00000000001
if( abs( x - y ) < eps ) {
printf("EQUAL!");
}
#include <stdio.h>
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || x > y){
/* Are not Equal */
}else{
/* Are Equal, foo() will be called here\n" */
printf("yes");
}
}
prints yes

Flooring floating-point modulo

I want to create a modulo-like function which can work with double-precision floats rather than ints. Another important factor is that the function must round towards negative infinity, rather than zero.
I have a couple of methods which work, but I believe them to be slow for a function which will be called many times in loops:
// A suggested method
double reduce_range(double x, const double max) {
x /= max; // Normalize to [0,1)
x -= (int) x;
x += 1.0;
x -= (int) x;
return x * max; // Denormalize
}
// My own simple implementation
double reduce_range(const double x, const double max) {
return x - floor(x / max) * max;
}
Both seem to work, but the second uses floor (which seems to be a bit of a bottleneck for these sorts of things) and the first repeatedly casts to int and subtracts. Is there not some faster way to do this (or to allow the compiler to take care of it)?
Alternatively, how about this:
double reduce_range(double x, const double max) {
x = fmod(x, max);
if(x < 0) x += max;
return x;
}
Is it going to be greatly slowed down by the branching if?
Edit: some example inputs and outputs:
(5.0, 7.0) >> 5.0
(8.5, 7.0) >> 1.5
(-2.3, 7.0) >> 4.7
If you are worried about the branch, then possibly this might be better, if it's cheaper to load an integer into the fpu:
x += max * (x < 0);

taylor series with error at most 10^-3

I'm trying to calculate the the taylor series of cos(x) with error at most 10^-3 and for all x ∈ [-pi/4, pi/4], that means my error needs to be less than 0.001. I can modify the x +=in the for loop to have different result. I tried several numbers but it never turns to an error less than 0.001.
#include <stdio.h>
#include <math.h>
float cosine(float x, int j)
{
float val = 1;
for (int k = j - 1; k >= 0; --k)
val = 1 - x*x/(2*k+2)/(2*k+1)*val;
return val;
}
int main( void )
{
for( double x = 0; x <= PI/4; x += 0.9999 )
{
if(cosine(x, 2) <= 0.001)
{
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
return 0;
}
I'm also doing this for e^x too. For this part, x must in [-2,2] .
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int i = n - 1; i > 0; --i )
sum = 1 + x * sum / i;
return sum;
}
int main( void )
{
// change the number of x in for loop so you can have different range
for( float x = -2.0f; x <= 2.0f; x += 1.587 )
{
// change the frist parameter to have different n value
if(exponential(5, x) <= 0.001)
{
printf("e^x = %f\n", exponential(5, x));
}
printf("e^x = %f\n", exponential(5, x));
}
return 0;
}
But whenever I changed the number of terms in the for loop, it always have an error that is greater than 1. How am I suppose to change it to have errors less than 10^-3?
Thanks!
My understanding is that to increase precision, you would need to consider more terms in the Taylor series. For example, consider what happens when
you attempt to calculate e(1) by a Taylor series.
$e(x) = \sum\limits_{n=0}^{\infty} frac{x^n}{n!}$
we can consider the first few terms in the expansion of e(1):
n value of nth term sum
0 x^0/0! = 1 1
1 x^1/1! = 1 2
2 x^2/2! = 0.5 2.5
3 x^3/3! = 0.16667 2.66667
4 x^4/4! = 0.04167 2.70834
You should notice two things, first that as we add more terms we are getting closer to the exact value of e(1), also that the difference between consecutive sums are getting smaller.
So, an implementation of e(x) could be written as:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
typedef float (*term)(int, int);
float evalSum(int, int, int, term);
float expTerm(int, int);
int fact(int);
int mypow(int, int);
bool sgn(float);
const int maxTerm = 10; // number of terms to evaluate in series
const float epsilon = 0.001; // the accepted error
int main(void)
{
// change these values to modify the range and increment
float start = -2;
float end = 2;
float inc = 1;
for(int x = start; x <= end; x += inc)
{
float value = 0;
float prev = 0;
for(int ndx = 0; ndx < maxTerm; ndx++)
{
value = evalSum(0, ndx, x, expTerm);
float diff = fabs(value-prev);
if((sgn(value) && sgn(prev)) && (diff < epsilon))
break;
else
prev = value;
}
printf("the approximate value of exp(%d) is %f\n", x, value);
}
return 0;
}
I've used as a guess that we will not need to use more then ten terms in the expansion to get to the desired precision, thus the inner for loop is where we loop over values of n in the range [0,10].
Also, we have several lines dedicated to checking if we reach the required precision. First I calculate the absolute value of the difference between the current evaluation and the previous evaluation, and take the absolute difference. Checking if the difference is less than our epsilon value (1E-3) is on of the criteria to exit the loop early. I also needed to check that the sign of of the current and the previous values were the same due to some fluctuation in calculating the value of e(-1), that is what the first clause in the conditional is doing.
float evalSum(int start, int end, int val, term fnct)
{
float sum = 0;
for(int n = start; n <= end; n++)
{
sum += fnct(n, val);
}
return sum;
}
This is a utility function that I wrote to evaluate the first n-terms of a series. start is the starting value (which is this code always 0), and end is the ending value. The final parameter is a pointer to a function that represents how to calculate a given term. In this code, fnct can be a pointer to any function that takes to integer parameters and returns a float.
float expTerm(int n, int x)
{
return (float)mypow(x,n)/(float)fact(n);
}
Buried down in this one-line function is where most of the work happens. This function represents the closed form of a Taylor expansion for e(n). Looking carefully at the above, you should be able to see that we are calculating $\fract{x^n}{n!}$ for a given value of x and n. As a hint, for doing the cosine part you would need to create a function to evaluate the closed for a term in the Taylor expansion of cos. This is given by $(-1)^n\fact{x^{2n}}{(2n)!}$.
int fact(int n)
{
if(0 == n)
return 1; // by defination
else if(1 == n)
return 1;
else
return n*fact(n-1);
}
This is just a standard implementation of the factorial function. Nothing special to see here.
int mypow(int base, int exp)
{
int result = 1;
while(exp)
{
if(exp&1) // b&1 quick check for odd power
{
result *= base;
}
exp >>=1; // exp >>= 1 quick division by 2
base *= base;
}
return result;
}
A custom function for doing exponentiation. We certainly could have used the version from <math.h>, but because I knew we would only be doing integer powers we could write an optimized version. Hint: in doing cosine you probably will need to use the version from <math.h> to work with floating point bases.
bool sgn(float x)
{
if(x < 0) return false;
else return true;
}
An incredibly simple function to determine the sign of a floating point value, returning true is positive and false otherwise.
This code was compiled on my Ubuntu-14.04 using gcc version 4.8.4:
******#crossbow:~/personal/projects$ gcc -std=c99 -pedantic -Wall series.c -o series
******#crossbow:~/personal/projects$ ./series
the approximate value of exp(-2) is 0.135097
the approximate value of exp(-1) is 0.367857
the approximate value of exp(0) is 1.000000
the approximate value of exp(1) is 2.718254
the approximate value of exp(2) is 7.388713
The expected values, as given by using bc are:
******#crossbow:~$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
e(-2)
.13533528323661269189
e(-1)
.36787944117144232159
e(0)
1.00000000000000000000
e(1)
2.71828182845904523536
e(2)
7.38905609893065022723
As you can see, the values are well within the tolerances that you requests. I leave it as an exercise to do the cosine part.
Hope this helps,
-T
exp and cos have power series that converge everywhere on the real line. For any bounded interval, e.g. [-pi/4, pi/4] or [-2, 2], the power series converge not just pointwise, but uniformly to exp and cos.
Pointwise convergence means that for any x in the region, and any epsilon > 0, you can pick a large enough N so that the approximation you get from the first N terms of the taylor series is within epsilon of the true value. However, with pointwise convergence, the N may be small for some x's and large for others, and since there are infinitely many x's there may be no finite N that accommodates them all. For some functions that really is what happens sometimes.
Uniform convergence means that for any epsilon > 0, you can pick a large enough N so that the approximation is within epsilon for EVERY x in the region. That's the kind of approximation that you are looking for, and you are guaranteed that that's the kind of convergence that you have.
In principle you could look at one of the proofs that exp, cos are uniformly convergent on any finite domain, sit down and say "what if we take epsilon = .001, and the regions to be ...", and compute some finite bound on N using a pen and paper. However most of these proofs will use at some steps some estimates that aren't sharp, so the value of N that you compute will be larger than necessary -- maybe a lot larger. It would be simpler to just implement it for N being a variable, then check the values using a for-loop like you did in your code, and see how large you have to make it so that the error is less than .001 everywhere.
So, I can't tell what the right value of N you need to pick is, but the math guarantees that if you keep trying larger values eventually you will find one that works.

Approximation of arcsin in C

I've got a program that calculates the approximation of an arcsin value based on Taylor's series.
My friend and I have come up with an algorithm which has been able to return the almost "right" values, but I don't think we've done it very crisply. Take a look:
double my_asin(double x)
{
double a = 0;
int i = 0;
double sum = 0;
a = x;
for(i = 1; i < 23500; i++)
{
sum += a;
a = next(a, x, i);
}
}
double next(double a, double x, int i)
{
return a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2)));
}
I checked if my_pow works correctly so there's no need for me to post it here as well. Basically I want the loop to end once the difference between the current and next term is more or equal to my EPSILON (0.00001), which is the precision I'm using when calculating a square root.
This is how I would like it to work:
while(my_abs(prev_term - next_term) >= EPSILON)
But the function double next is dependent on i, so I guess I'd have to increment it in the while statement too. Any ideas how I should go about doing this?
Example output for -1:
$ -1.5675516116e+00
Instead of:
$ -1.5707963268e+00
Thanks so much guys.
Issues with your code and question include:
Your image file showing the Taylor series for arcsin has two errors: There is a minus sign on the x5 term instead of a plus sign, and the power of x is shown as xn but should be x2n+1.
The x factor in the terms of the Taylor series for arcsin increases by x2 in each term, but your formula a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2))) divides by x2 in each term. This does not matter for the particular value -1 you ask about, but it will produce wrong results for other values, except 1.
You ask how to end the loop once the difference in terms is “more or equal to” your epsilon, but, for most values of x, you actually want less than (or, conversely, you want to continue, not end, while the difference is greater than or equal to, as you show in code).
The Taylor series is a poor way to evaluate functions because its error increases as you get farther from the point around which the series is centered. Most math library implementations of functions like this use a minimax series or something related to it.
Evaluating the series from low-order terms to high-order terms causes you to add larger values first, then smaller values later. Due to the nature of floating-point arithmetic, this means that accuracy from the smaller terms is lost, because it is “pushed out” of the width of the floating-point format by the larger values. This effect will limit how accurate any result can be.
Finally, to get directly to your question, the way you have structured the code, you directly update a, so you never have both the previous term and the next term at the same time. Instead, create another double b so that you have an object b for a previous term and an object a for the current term, as shown below.
Example:
double a = x, b, sum = a;
int i = 0;
do
{
b = a;
a = next(a, x, ++i);
sum += a;
} while (abs(b-a) > threshold);
using Taylor series for arcsin is extremly imprecise as the stuff converge very badly and there will be relatively big differencies to the real stuff for finite number of therms. Also using pow with integer exponents is not very precise and efficient.
However using arctan for this is OK
arcsin(x) = arctan(x/sqrt(1-(x*x)));
as its Taylor series converges OK on the <0.0,0.8> range all the other parts of the range can be computed through it (using trigonometric identities). So here my C++ implementation (from my arithmetics template):
T atan (const T &x) // = atan(x)
{
bool _shift=false;
bool _invert=false;
bool _negative=false;
T z,dz,x1,x2,a,b; int i;
x1=x; if (x1<0.0) { _negative=true; x1=-x1; }
if (x1>1.0) { _invert=true; x1=1.0/x1; }
if (x1>0.7) { _shift=true; b=::sqrt(3.0)/3.0; x1=(x1-b)/(1.0+(x1*b)); }
x2=x1*x1;
for (z=x1,a=x1,b=1,i=1;i<1000;i++) // if x1>0.8 convergence is slow
{
a*=x2; b+=2; dz=a/b; z-=dz;
a*=x2; b+=2; dz=a/b; z+=dz;
if (::abs(dz)<zero) break;
}
if (_shift) z+=pi/6.0;
if (_invert) z=0.5*pi-z;
if (_negative) z=-z;
return z;
}
T asin (const T &x) // = asin(x)
{
if (x<=-1.0) return -0.5*pi;
if (x>=+1.0) return +0.5*pi;
return ::atan(x/::sqrt(1.0-(x*x)));
}
Where T is any floating point type (float,double,...). As you can see you need sqrt(x), pi=3.141592653589793238462643383279502884197169399375105, zero=1e-20 and +,-,*,/ operations implemented. The zero constant is the target precision.
So just replace T with float/double and ignore the :: ...
so I guess I'd have to increment it in the while statement too
Yes, this might be a way. And what stops you?
int i=0;
while(condition){
//do something
i++;
}
Another way would be using the for condition:
for(i = 1; i < 23500 && my_abs(prev_term - next_term) >= EPSILON; i++)
Your formula is wrong. Here is the correct formula: http://scipp.ucsc.edu/~haber/ph116A/taylor11.pdf.
P.S. also note that your formula and your series are not correspond to each other.
You can use while like this:
while( std::abs(sum_prev - sum) < 1e-15 )
{
sum_prev = sum;
sum += a;
a = next(a, x, i);
}

Resources