Прошло много времени с тех пор, как я написал чистый C, поэтому здесь он написан на C ++ (я думаю, что единственное отличие - это функция вывода, поэтому вы должны быть в состоянии следовать ей):
#include <iostream>
using namespace std;
const static double CUTOFF = 1e-10;
double log2_aux(double x, double power, double twoToTheMinusN, unsigned int accumulator) {
if (twoToTheMinusN < CUTOFF)
return accumulator * twoToTheMinusN * 2;
else {
int thisBit;
if (x > power) {
thisBit = 1;
x /= power;
}
else
thisBit = 0;
accumulator = (accumulator << 1) + thisBit;
return log2_aux(x, sqrt(power), twoToTheMinusN / 2.0, accumulator);
}
}
double mylog2(double x) {
if (x < 1)
return -mylog2(1.0/x);
else if (x == 1)
return 0;
else if (x > 2.0)
return mylog2(x / 2.0) + 1;
else
return log2_aux(x, 2.0, 1.0, 0);
}
int main() {
cout << "5 " << mylog2(5) << "\n";
cout << "1.25 " << mylog2(1.25) << "\n";
return 0;
}
Функция «mylog2» выполняет простую хитрость в журнале, чтобы получить связанный номер от 1 до 2, затем вызывает log2_aux с этим номером.
log2_aux более или менее следует алгоритму, с которым Scorpi0 ссылается выше. На каждом шаге вы получаете 1 бит результата. Когда у вас будет достаточно битов, остановитесь.
Если вы сможете получить копию, лекция Фейнмана по физике, номер 23, начинается с отличного объяснения журналов и более или менее того, как выполнить это преобразование. Значительно превосходит статью в Википедии.