| New Reply |
I need a method to calculate ln(x) for small x, other than Taylor series method |
Share Thread | Thread Tools |
| Jan26-11, 04:43 AM | #1 |
|
|
I need a method to calculate ln(x) for small x, other than Taylor series method
I'm aiming to calculate ln(x) numerically. I'm using the following procedure for this:
1) If x is greater or equal to 1, use Newton's method. 2) If x is smaller between 0 and 1, use Taylor series expansion. Newton's method works good, but I have problems with Taylor series expansion method. [latex]\ln(1+x)=\sum_{n=1}^\infty \frac{(-1)^{n+1}}{n} x^n = x - \frac{x^2}{2} + \frac{x^3}{3} - \cdots \quad{\rm for}\quad \left|x\right| \leq 1\quad[/latex] Sum of this series is [latex]\small -\infty\normalsize[/latex] for [latex]\small x=-1\normalsize[/latex], but when you try to take sum of it using a computer, it doesn't converge because of computing limitations (like using truncated series). I can't either use Newton's method for this interval, because it has a bad performance for small x values (neither it converges for small x). For x=0.000001; ln(x) = -13.8155... (actual) ln(x) = -1.71828... (calculated) (The summation goes on until absolute value of any element of the series is below a user defined [latex]\epsilon[/latex] value, which is equal to [latex]1.0 \times 10^{-14}[/latex] for this particular example.) I need a third method to calculate ln(x) for small x argument. Can you please suggest me one? |
| Jan26-11, 07:40 AM | #2 |
|
|
Maybe you could try directly evaluating the integral:
[tex]\int^{x}_{1}\frac{1}{x}dx[/tex] |
| Jan26-11, 02:09 PM | #3 |
|
Recognitions:
|
|
| Jan26-11, 02:12 PM | #4 |
|
|
I need a method to calculate ln(x) for small x, other than Taylor series methodCode:
// Public method
long double Math::ln(long double num) throw(MathInvalidArgument)
{
if (num < 0)
{
throw(MathInvalidArgument(L"You tried to take ln() of a negative number."));
}
else if (num == 0.0)
{
long double zero = 0.0;
return -1.0 / zero; // return minus infinity
}
else if (num <= 1.0)
{
return ln_ByTaylorSeriesExpansion(num);
}
else
{
return ln_ByNewtonsMethod(num);
}
}
// Private method
long double Math::ln_ByTaylorSeriesExpansion(long double arg)
{
arg -= 1.0; // We will use series expansion for ln(x+1)
long double Result = 0.0, NextSum;
long double power_of_arg_over_i = 1.0;
for (uint64_t i=1; true; i++)
{
power_of_arg_over_i *= arg / static_cast<long double>(i);
NextSum = -static_cast<long double>(MinusOneToThePowerOf(i)) * power_of_arg_over_i;
Result += NextSum;
if (abs(NextSum) < m_PRECISION_EPSILON)
{
break;
}
}
return Result;
}
// Private method
long double Math::ln_ByNewtonsMethod(long double arg)
{
long double x_k = 1.0, x_k1,asd;
for (uint64_t i=0; true; i++)
{
x_k1 = x_k - ((exp(x_k) - arg) / exp(x_k));
asd = abs(x_k1 - x_k); // This value does not approach to zero, fluctuating between 10^(-5) and 10^(-6)
if (abs(x_k1 - x_k) < m_PRECISION_EPSILON) break; // m_PRECISION_EPSILON is 10^(-14)
x_k = x_k1;
}
return x_k1;
}
|
| Jan26-11, 03:00 PM | #5 |
|
|
[tex]x,\ \frac{x^2}{2},\ \frac{x^3}{2*3},\ \frac{x^4}{2*3*4} ...[/tex] |
| Jan26-11, 03:05 PM | #6 |
|
|
Actually, I'm very sure that's the mistake you made since you got
[tex]e^{-(0.000001-1)} - 1\approx e-1\approx 1.7182818...[/tex] |
| Jan26-11, 03:11 PM | #7 |
|
|
The denominator term was was also accumulating into multiplication, so it was becoming factorial of the current for loop variable. It was calculating exp() instead of ln(), what an exciting coincidence... |
| Jan26-11, 03:13 PM | #8 |
|
|
My new code is:
Code:
long double Math::ln(long double num) throw(MathInvalidArgument)
{
if (num < 0)
{
throw(MathInvalidArgument(L"You tried to take ln() of a negative number."));
}
else if (num == 0.0)
{
long double zero = 0.0;
return -1.0 / zero; // return minus infinity
}
else if (num <= 1.0)
{
return ln_ByTaylorSeriesExpansion(num);
}
else
{
return ln_ByNewtonsMethod(num);
}
}
long double Math::ln_ByTaylorSeriesExpansion(long double arg)
{
arg -= 1.0; // We will use series expansion for ln(x+1)
long double Result = 0.0, NextSum;
long double power_of_arg = 1.0, power_of_arg_over_i;
for (uint64_t i=1; true; i++)
{
power_of_arg *= arg;
power_of_arg_over_i = power_of_arg / static_cast<long double>(i);
NextSum = -static_cast<long double>(MinusOneToThePowerOf(i)) * power_of_arg_over_i;
Result += NextSum;
if (abs(NextSum) < m_PRECISION_EPSILON)
{
break;
}
}
return Result;
}
long double Math::ln_ByNewtonsMethod(long double arg)
{
long double x_k = 1.0, x_k1;
for (uint64_t i=0; true; i++)
{
x_k1 = x_k - ((exp(x_k) - arg) / exp(x_k));
if (abs(x_k1 - x_k) < m_PRECISION_EPSILON) break;
x_k = x_k1;
}
return x_k1;
}
|
| Jan26-11, 03:13 PM | #9 |
Recognitions:
|
When 0 < x < 1, you could use
ln(x) = -ln(1/x) |
| Jan26-11, 03:15 PM | #10 |
|
|
This way I can always use Newton's method, it is better since it converges super fast. Thanks a lot! |
| Jan26-11, 03:27 PM | #11 |
|
|
For example, suppose that you want to calculate ln(0.000001) You send it into Newton's algorithm in this form -ln(1000000) I need to calculate exp(1000000) inside the Newton's algorithm, but obviously it is not possible because of the hardware and software limitations. And I also realized that, with this code, there is a very low limit for the argument of ln(). I need to work around this problem. |
| Jan26-11, 03:46 PM | #12 |
|
|
[tex]\ln{(a\cdot 10^{n})}=\ln{a}+n\ln{10}[/tex] |
| Jan26-11, 04:40 PM | #13 |
|
Recognitions:
|
Hmmm, I must be missing something. I had no problem at all finding ln(0.000001) using hkBattousai's algorithm for Newton's method. It reduces to xk+1 = xk - 1 + arg/exp(xk).
|
| New Reply |
| Tags |
| converge, logarithm, newton, numeric, taylor |
| Thread Tools | |
Similar Threads for: I need a method to calculate ln(x) for small x, other than Taylor series method
|
||||
| Thread | Forum | Replies | ||
| Taylor Series Method Integral | Calculus & Beyond Homework | 3 | ||
| Taylor method for IVPs | Differential Equations | 2 | ||
| Expanding a small oscillation potential in taylor series | Classical Physics | 2 | ||
| What method to calculate intergration? | Calculus | 4 | ||
| Taylor Series Starting Method | Calculus & Beyond Homework | 2 | ||