C implementation of power function - c

I am a beginner trying to comprehend this innocent C function:
Given two numbers x and y, this function computes the power of x raised to y.
/* Function to calculate x raised to the power y */
int power(int x, unsigned int y)
{
if( y == 0)
return 1;
else if (y%2 == 0)
return power(x, y/2)*power(x, y/2); //what's happening here?
else
return x*power(x, y/2)*power(x, y/2);
}
I am trying hard to trace the part where they multiply the return values from two functions. Suppose I pass in 4 and 3 as x and y, My function jumps to the second else part. and I return 4*(power(4,1)*power(4,1))
as far as my understanding goes, the next call is to 4*power(4,0)*power(4*0) and since y==0 returns 1, it should be 4*1*1 where I want 4*4*4. I am missing something here. What is this algorithm exactly doing?
The logic behind this function is to multiply x, y times. Can anyone please tell me how this simple division arithmetic (or divide and conquer) results in realizing the logic? Thanks in advance.

The algorithm used is exponentiation by squaring. It is divided into two parts, for a positive integer n
Therefore, the above function, for even exponent will return
power(x, y/2)*power(x, y/2);
and for odd exponent will return
x*power(x, y/2)*power(x, y/2);
It will calculate the power in order log(n) time.
For 25 it will be executed as:
5 is odd therefore return 2*power(2, 5/2)*power(2, 5/2) will be executed.
5/2 = 2, an even therefore return power(2, 2/2)*power(2, 2/2) will be executed.
2/2 = 1 is odd therefore return 2*power(2, 1/2)*power(2, 1/2) will be executed.
1/2 = 0, base condition therefore for both of power(2, 1/2), 1 will be returned.
So,
return 2*power(2, 1/2)*power(2, 1/2) will return 2*1*1 = 2 to its caller.
return power(2, 2/2)*power(2, 2/2) will return 2*2 = 4 to its caller.
return 2*power(2, 5/2)*power(2, 5/2) will return 2*4*4 = 32 to its caller.
A more efficient version would be
int power(int x, unsigned int y)
{
if( y == 0)
return 1;
int t = power(x, y/2); // power is called only once instead of twice.
return y%2 ? x*t*t : t*t;
}

For simplicity, the following does a power and demonstrates recursion in an easier to understand manner:
int power(int x, unsigned int y)
{
if( y == 0)
return 1;
return x * power(x, y-1);
}
This shows a simple way to use recursion to handle a power calc. The method you have will still roughly do what this does, but it's maximum stack depth will be much better (it will recurse less) because it divides the work up a bit better.
Not sure why you'd use either in the real world though. Iteration would probably be far superior, or perhaps a logarithm - multiply exponent - antilog approach (which would handle franctional exponents as well).
In addition, this type of calculation is also prone to overflow integer values really, really fast as well so please beware.

Related

How to find remainder of a double in C? Modulo only works for integers

This is what I've found so far online,
int main(void)
{
long a = 12345;
int b = 10;
int remain = a - (a / b) * b;
printf("%i\n", remain);
}
First I wonder how the formula works. Maybe i cant do math, but the priority of operations here seems a bit odd. If i run this code the expected answer of 5 is printed. But I dont get how (a / b) * b doesn't cancel out to 'a' leading to a - a = 0.
Now, this only works for int and long, as soon as double are involved it doesn't work anymore. Anyone might tell me why? Is there an alternative to modulo that works for double?
Also I'm not sure if i understand up to what value a long can go, i found online that the upper limit was 2147483647 but when i input bigger numbers such as the one in 'a' the code runs without any issue up to a certain point...
Thanks for your help I'm new to coding and trying to learn!
Given two double finite numbers x and y, with y not equal to zero, fmod(x, y) produces the remainder of x when divided by y. Specifically, it returns x − ny, where n is chosen so that x − ny has the same sign as x and is smaller in magnitude than y. (So, if x is positive, 0 ≤ fmod(x, y) < x, and, if x is negative, x < fmod(x, y) ≤ 0.)
fmod is declared in <math.h>.
A properly implemented fmod returns an exact result; there is no floating-point error, since the specified result is always representable.
The C standard also specifies remquo to return the remainder and some low bits (at least three) of the quotient n and remainder with a variation on the definition of the remainder. It also specifies variants of these functions for float and long double.
Naive implementation. Limited range. Adds additional floating point imprecisions (as it does some arithmetic)
double naivemod(double x)
{
return x - (long long)x;
}
int main(void)
{
printf("%.50f\n", naivemod(345345.567567756));
printf("%.50f\n", naivemod(.0));
printf("%.50f\n", naivemod(10.5));
printf("%.50f\n", naivemod(-10.0/3));
}

Why is pow() function in C giving wrong answer when it is odd exponential of 10 in a loop? [duplicate]

This question already has answers here:
Why pow(10,5) = 9,999 in C++
(8 answers)
Closed 2 years ago.
#include <stdio.h>
#include <math.h>
int main()
{
int loop, place_value=0, c = 5;
for(loop = 0; loop < c; loop++)
{
place_value = 0;
place_value = pow(10, loop);
printf("%d \n", place_value);
}
return 0;
}
This code gives
10
99
1000
9999
Why is 99 and 9999 there in 3rd and 5th line instead of 100 and 10000 respectively?
When asking for power normally, it gives right answer.
#include <stdio.h>
#include <math.h>
int main()
{
printf ("%d", (int) pow (10,3 ));
return 0;
}
1000
pow is a difficult routine to implement, and not all implementations give good results. Roughly speaking, the core algorithm for pow(x, y) computes a logarithm from (a part of) x, multiplies it by y, and computes an exponential function on the product. Doing this in floating-point introduces rounding errors that are hard to control.
The result is that the computed result for pow(10, 4) may be something near 10,000 but slightly less or greater. If it is less, than converting it to an integer yields 9999.
When you use arguments hard-coded in source code, the compiler may compute the answer during compilation, possibly using a different algorithm. For example, when y is three, it may simply multiply the first argument by itself, as in x*x*x, rather than using the logarithm-exponent algorithm.
As for why the low result happens with the odd numbers you have tested, consider what happens when we multiply 5.45454545 by various powers of 10 and round to an integer. 5.45454545 rounds down to 5. 54.5454545 rounds up to 55. 545.454545 rounds down to 545. The rounding up or down is a consequence of what fraction happens to land beyond the decimal point. For your cases with pow(10, loop), the bits of the logarithm of 10 may just happen to give this pattern with the few odd numbers you tried.
pow(x, y) function translate more or less to exp(log(x) * y), which will give a result that is not quite the same as x ^ y.
In order to solve this issue you can round this:
round(pow(x, y))
The rule of thumb: never use floating point functions (especially such a complicated ones like pow or log) with integer numbers.
Simply implement integer pow
unsigned intpow(unsigned x)
{
unsigned result = 1;
while(x --) result *= 10;
return result;
}
it will be much faster or even (the fastest one)
int intpow1(unsigned x)
{
const static unsigned vals[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, /* ... */};
#if defined(CHECK_OVERFLOW)
if(x >= sizeof(vals)/ sizeof(vals[0])) return -1;
#endif
return vals[x];
}

Recursively calculate integer sqrts with C

I adapted some python code I found here to calculate the sqrt of a number if it exists as an integer using bitwise operations. here is my code.
int ft_sqrt(int nb){
int smallcandidate;
int largecandidate;
if (nb < 0){
return (0);
}else if (nb < 2){
return (nb);
}else{
smallcandidate = ft_sqrt(nb >> 2) << 1;
largecandidate = smallcandidate + 1;
if (largecandidate * largecandidate > nb){
return (smallcandidate);
}
else{
return (largecandidate);
}
}
}
This works for every number i've tested (within the bounds of what an integer can hold), except for 3. Why is this? and how can i fix it?
Sorry, but you had better to use an iterative function, as you see your recursion is final recursion, that can be collapsed to a while loop. Your algorithm is:
#include <stdio.h>
unsigned isqrt(unsigned x)
{
unsigned quot = 1, mean = x; /* isqrt must be between these two */
/* we begin with extreme numbers and for each pair of (quot,mean),
* the first, below the square root, and the other above, we get
* mean value of the two (lesser than previous) and the
* quotient (above the prev. value, but still less than the
* square root, so closer to it) to get a better approach */
while (quot < mean) {
mean = (mean + quot) >> 1;
quot = x / mean;
}
/* quot is always <= mean so finally it should be the same,
* we can return quot or mean, indistinctly. */
return mean;
}
int main() /* main test function, eliminate to use the above. */
{
unsigned n;
while (scanf("%u", &n) == 1) {
printf("isqrt(%u) ==> %u\n", n, isqrt(n));
}
}
EDIT
This algorithm is based on the fact that the geometric mean is always closer to 1 than the arithmetic mean. So we take two approximations (the source number and 1, as their geometric mean is the square root) then we calculate their arithmetic mean (so the value obtained is between both, and so, closer to the geometric mean) then we divide the original number by the arithmetic mean so both aproximations multiply to the original data (and their geometric mean is, again, the square root). As, in each loop the arithmetic mean is closer to the geometric mean, so must be the quotient (and so the quotient to the geometric mean), leading to two numbers that are closer to the square root. We continue the algorithm until both numbers are equal (a / sqrt(a) = sqrt(a), and (sqrt(a) + sqrt(a))/2 = sqrt(a)) or, due to rounding errors, they cross over. ---this happens with integers---

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

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;
}

How will you implement pow(a,b) in C ? condition follows --

without using multiplication or division operators.
You can use only add/substract operators.
A pointless problem, but solvable with the properties of logarithms:
pow(a,b) = exp( b * log(a) )
= exp( exp(log(b) + log(log(a)) )
Take care to insure that your exponential and logarithm functions are using the same base.
Yes, I know how to use a sliderule. Learning that trick will change your perspective of logarithms.
If they are integers, it's simple to turn pow (a, b) into b multiplications of a.
pow(a, b) = a * a * a * a ... ; // do this b times
And simple to turn a * a into additions
a * a = a + a + a + a + ... ; // do this a times
If you combine them, you can make pow.
First, make mult(int a, int b), then use it to make pow.
A recursive solution :
#include<stdio.h>
int multiplication(int a1, int b1)
{
if(b1)
return (a1 + multiplication(a1, b1-1));
else
return 0;
}
int pow(int a, int b)
{
if(b)
return multiplication(a, pow(a, b-1));
else
return 1;
}
int main()
{
printf("\n %d", pow(5, 4));
}
You've already gotten answers purely for FP and purely for integers. Here's one for a FP number raised to an integer power:
double power(double x, int y) {
double z = 1.0;
while (y > 0) {
while (!(y&1)) {
y >>= 2;
x *= x;
}
--y;
z = x * z;
}
return z;
}
At the moment this uses multiplication. You can implement multiplication using only bit shifts, a few bit comparisons, and addition. For integers it looks like this:
int mul(int x, int y) {
int result = 0;
while (y) {
if (y&1)
result += x;
x <<= 1;
y >>= 1;
}
return result;
}
Floating point is pretty much the same, except you have to normalize your results -- i.e., in essence, a floating point number is 1) a significand expressed as a (usually fairly large) integer, and 2) a scale factor. If you want to produce normal IEEE floating point numbers a few parts get a bit ugly though -- for example, the scale factor is stored as a "bias" number instead of any of the usual 1's complement, 2's complement, etc., so working with it is clumsy (basically, each operation you subtract off the bias, do the operation, check for overflow, and (assuming it hasn't overflowed) add the bias back on again).
Doing the job without any kind of logical tests sounds (to me) like it probably wasn't really intended. For quite a few computer architecture classes, it's interesting to reduce a problem to primitive operations you can express directly in hardware (e.g., bit shifts, bitwise-AND, -OR and -NOT, etc.) The implementation shown above fits that reasonably well (if you want to get technical, an adder takes a few gates, but VHDL, Verilog, etc., but it's included in things like VHDL and Verilog anyway).

Resources