How can I write a power function myself?
Negative powers are not a problem, they're just the inverse (1/x
) of the positive power.
Floating point powers are just a little bit more complicated; as you know a fractional power is equivalent to a root (e.g. x^(1/2) == sqrt(x)
) and you also know that multiplying powers with the same base is equivalent to add their exponents.
With all the above, you can:
- Decompose the exponent in a integer part and a rational part.
- Calculate the integer power with a loop (you can optimise it decomposing in factors and reusing partial calculations).
- Calculate the root with any algorithm you like (any iterative approximation like bisection or Newton method could work).
- Multiply the result.
- If the exponent was negative, apply the inverse.
Example:
2^(-3.5) = (2^3 * 2^(1/2)))^-1 = 1 / (2*2*2 * sqrt(2))
The most efficient way to implement an integer based power function pow(int, int)
Exponentiation by squaring.
int ipow(int base, int exp)
{
int result = 1;
for (;;)
{
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
break;
base *= base;
}
return result;
}
This is the standard method for doing modular exponentiation for huge numbers in asymmetric cryptography.
How is pow() calculated in C?
If you're curious how the pow
function might be implemented in practice, you can look at the source code. There is a kind of "knack" to searching through unfamiliar (and large) codebases to find the section you are looking for, and it's good to get some practice.
One implementation of the C library is glibc, which has mirrors on GitHub. I didn't find an official mirror, but an unofficial mirror is at https://github.com/lattera/glibc
We first look at the math/w_pow.c
file which has a promising name. It contains a function __pow
which calls __ieee754_pow
, which we can find in sysdeps/ieee754/dbl-64/e_pow.c
(remember that not all systems are IEEE-754, so it makes sense that the IEEE-754 math code is in its own directory).
It starts with a few special cases:
if (y == 1.0) return x;
if (y == 2.0) return x*x;
if (y == -1.0) return 1.0/x;
if (y == 0) return 1.0;
A little farther down you find a branch with a comment
/* if x<0 */
Which leads us to
return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */
So you can see, for negative x
and integer y
, the glibc version of pow
will compute pow(-x,y)
and then make the result negative if y
is odd.
This is not the only way to do things, but my guess is that this is common to many implementations. You can see that pow
is full of special cases. This is common in library math functions, which are supposed to work correctly with unfriendly inputs like denormals and infinity.
The pow
function is especially hard to read because it is heavily-optimized code which does bit-twiddling on floating-point numbers.
The C Standard
The C standard (n1548 §7.12.7.4) has this to say about pow
:
A domain error occurs if x is finite and negative and y is finite and not an integer value.
So, according to the C standard, negative x
should work.
There is also the matter of appendix F, which gives much tighter constraints on how pow
works on IEEE-754 / IEC-60559 systems.
Write Pow Function Without math.h in C
Everything seems perfect except for one condition :- when b<0
.
For b<0,simply return
return (1.0/a)*MyPow(a,abs(b)-1); //where abs(b) is absolute value of b.
OR
return (1.0/a)*(MyPow(a,b+1));
Also,your definition of function is not valid for performing negative exponentiation,you should change it to
float MyPow(int a,int b)
how could I use the power function in c/c++ without pow(), functions, or recursion
It is a series. Replace pow()
based on the previous iteration. @Bathsheba
Code does not need to call pow()
. It can form pow(x, 5 * i - 1)
and pow(-1, i - 1)
, since both have an int
exponent based on the iterator i
, from the prior loop iteration.
Example:
Let f(x, i) = pow(x, 5 * i - 1)
Then f(x, 1) = x*x*x*x
and f(x, i > 1) = f(x, i-1) * x*x*x*x*x
double power_n1 = 1.0;
double power_x5 = x*x*x*x;
for (int i = 1; i < j + 1; i++)
// sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
sum += power_n1 / (5 * i - 1) * power_x5;
power_n1 = -power_n1;
power_x5 *= x*x*x*x*x;
}
Does pow() work for int data type in C?
Floating point precision is doing its job here. The actual working of pow
is using log
pow(a, 2) ==> exp(log(a) * 2)
Look at math.h
library which says:
###<math.h>
/* Excess precision when using a 64-bit mantissa for FPU math ops can
cause unexpected results with some of the MSVCRT math functions. For
example, unless the function return value is stored (truncating to
53-bit mantissa), calls to pow with both x and y as integral values
sometimes produce a non-integral result. ... */
Just add 0.5
to the return value of pow
and then convert it to int
.
b = (int)(pow(a,2) + 0.5);
So, the answer to your question
Does pow() work for
int
data type in C?
Not always. For integer exponentiation you could implement your own function (this will work for 0 and +ve exp
only):
unsigned uint_pow(unsigned base, unsigned exp)
{
unsigned result = 1;
while (exp)
{
if (exp % 2)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
C - Writing a function for an exponent without using Pow
Try this:
long int x_to_the_n (int x,int n)
{
int i; /* Variable used in loop counter */
int number = 1;
for (i = 0; i < n; ++i)
number *= x;
return(number);
}
C++ program for power but without using pow function
The program must not use any pre-defined C++ functions (like pow function) for this task
You can use some piece of c++ code like follows, to compute xy, without using any predefined function:
int x = 5;
int y = 3;
int result = 1;
for(int i = 0; i < y; ++i)
{
result *= x;
}
cout << result << endl;
Output:
125
See a working sample here.
Pow function in C is outputting zero
More than likely, your problem is a common error when dealing with numbers in C. Consider this:
double recN = 1/N;
Here, you define the variable as double, but you then perform integer division. If N>1
then this will result in zero.
Instead, look for places you've done this type of calculation and convert it to:
double recN = 1.0/N;
Related Topics
Calling Constructor with Braces
Understanding Rvalue References
Check If Class Is Derived from a Specific Class (Compile, Runtime Both Answers Available)
Using 'Void' Template Arguments in C++
Dealing with Floating Point Exceptions
How to Find If a Variable Is Allocated in Stack or Heap
Where Ampersand "&" Can Be Put When Passing Argument by Reference
What Does Exactly the Warning Mean About Hidden Symbol Being Referenced by Dso
What Should the 'Pop()' Method Return When the Stack Is Empty
Understanding How Lambda Closure Type Has Deleted Default Constructor
Making Only One Column of a Qtreewidgetitem Editable
Undocumented Gcc Extension: Vla in Struct
What Do the C and C++ Standards Say About Bit-Level Integer Representation and Manipulation