I am trying to solve a problem posed in this question which asks that a program be written that calculates logarithms of numbers without including <math.h>.
I wrote the following program:
#include <stdio.h>
#define ln2 0.693147180559945
double power (double argu, int expo)
{
double power = 1;
for (int i = 0; i < expo; i++) { power *= argu; }
return power;
}
double log_2 (double argu)
{
int i = 0;
for (; (double)(1 << i) <= argu; i++) {}
i -= 1;
double who = (double)i, fra = 0;
for (int j = 1, k = 1; k < 450; j *= -1, k += 1)
{
fra += ((double)j / (double)k) * (power (((argu - (double)(1 << i)) / (double)(1 << i)), (double)k));
}
return who + (fra / ln2);
}
double log_b (unsigned int base, double argu)
{
return ((log_2(argu)) / (log_2(base)));
}
int main (void)
{
for (;;)
{
unsigned int base;
double argu;
printf ("Give me a nonzero positive integer base, b = ");
if (scanf ("%u", &base) != 1) { printf ("Error!!"); break; }
printf ("Give me a nonzero positive rational argument, x = ");
if (scanf ("%lf", &argu) != 1) { printf ("Error!!"); break; }
printf ("log_b(x) = %.12lf\n\n", log_b (base, argu));
}
return 1;
}
I used the following method; approximated the log base 2 using left shift and Taylor expanded around that approximation, see function log_2(); then changed the base from 2 by applying the fact that ratios of logarithms are base independent, see function log_b().
My programme works for other numbers but give it an argument larger than a billion, it hangs. I suspect, as 2^32 roughly equals 109, the computer is treating the variable double argu declared in the main() as an int instead of a double. Is my suspicion correct? If yes, then why is a double being treated as an int? On the other hand, if not, then why is the program not accepting arguments larger than a billion, a double should be able to accommodate numbers smaller than or equal to 253 right?
for (; (double)(1 << i) <= argu; i++) {}should befor (; (double)(1ULL << i) <= argu; i++) {}so you don't hit int limitsunsigned long longis 2^64 - 1 max, which means thatiis at most 63.DBL_MAX_EXP, however, is 1024. The only way not to hit the limit is to eschew integral types altogether.kby50each time until all the12digits after decimal point of the result disappeared. It turned out all the arguments converge within 50 iterations of the for loop except multiples of3, like1000,1000000and1000000000. Especially1000takes 450 iterations in order to disappear all the12digits after decimal point in result. This problem has been solved by chqrlie in his answer below. Now the for loop doesn't need to be this long any longer and converges within 35 iterations.double17 significant digits is a better goal given the commondoubleencoding of 53 binary digits. Instead I'd recommend to analyze the code and thedoubleencoding and instead of 450, 35, etc, and use constants from<float.h>or run time tests to drive the loop count. IAC, glad you found a better approach.