Solutia mea, desi contine ceva mai multe caractere decat cele postate anterior, adica 115 cu whitespace, se bazeaza pe ideea ca integrala din 1/x dx este ln(x). Astfel putem foarte usor face asta destul de precis, metode mai bune fiind regulile lui Simpson, dintre care este recomandata Simpson 3/8. Stiu ca este foarte lenta pt. numere mai mari, dar imi place deoarece este foarte simpla.
#define d double
d l(d x){d a=min(1.0,x);x=max(1.0,x);d r=0;while(a<x){r+=1/a*1e-6;a+=1e-6;}if(x-1<1e-6)r*=-1;return r;}
Codul curat si un exemplu de folosire:
#include <cstdio>
#include <algorithm>
using namespace std;
double ln(double x)
{
double dx = min(1.0, x);
x = max(1.0, x);
double result = 0.0;
while (dx < x)
{
result += 1 / dx * 1e-6;
dx += 1e-6;
}
if (x < 1)
result *= -1;
return result;
}
int main()
{
float x;
printf("x = ");
scanf("%f", &x);
printf("ln(%f) = %f\n", x, ln(x));
return 0;
}
O alta solutie ce mi-a venit in minte este bazata pe derivata lui a^x, dupa cum este cunoscut (a^x)' = a^x * ln(a). Codul bazat pe aceasta idee se afla mai jos si are 76 de caractere.
double f(double x){return (pow(x,2.0+1e-6)-pow(x,2.0))/1e-6/pow(x,2.0+1e-7);}
Codul curat si un exemplu de utilizare:
#include <cstdio>
#include <cmath>
double ln(double x)
{
double df = pow(x, 2.0 + 1e-6) - pow(x, 2.0);
double dx = 1e-6;
double f = pow(x, 2.0 + dx / 2);
return (df / dx) / f;
}
int main()
{
float x;
printf("x = ");
scanf("%f", &x);
printf("ln(%f) = %f\n", x, ln(x));
return 0;
}
Edit: Acum am vazut ca nu am voie sa folosesc functia putere asa ca am adaptat ultima solutie sa foloseasca radical de ordinul doi pentru a obtine o putere rationala de ordinul 1e-6. Codul sub aceasta forma este mai jos.
double ln(double x)
{
double rx = x;
for (int i = 1; i <= 20; i++)
rx = sqrt(rx);
double df = x * x * rx - x * x;
double dx = 1 / (double)(1 << 20);
return (df / dx) / (x * x * sqrt(rx));
}