// this method is slow public static decimal Ln(decimal x) { if (x <= 0M) { throw new ArgumentOutOfRangeException("x"); } // algorithm is Newton's method decimal expy = 1; decimal y = 2M * (x - expy) / (x + expy); for (int i = 0; i < 1000 * 1000; ++i) { expy = Exp(y); decimal diff = 2M * (x - expy) / (x + expy); if (WWDecimalMath.IsRelativelySmall(diff, y)) { break; } y += diff; } return(y); }
public static decimal Exp(decimal x) { decimal y = 0M; // algorithm is simple Taylor series decimal diff = 1M; for (int i = 1; i < 1000 * 1000; ++i) { y += diff; diff *= x / i; if (WWDecimalMath.IsRelativelySmall(diff, y)) { break; } } return(y); }
public static decimal Sqrt(decimal v) { if (v < 0M) { throw new ArgumentOutOfRangeException("v"); } // Algorithm is Newton's method // https://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number // x^2 = v // f(x) = x^2 - v // f'(x) = 2x // x0 = 10 // x1 = x0 - f(x0)/f'(x0) // x2 = x1 - f(x1)/f'(x1) // f(x)/f'(x) = (x^2-v)/(2x) = (1/2)*(x -v/x) decimal x = 10M; for (int i = 0; i < 128; ++i) { decimal diff = (x - v / x) / 2; if (WWDecimalMath.IsRelativelySmall(diff, x)) { break; } x -= diff; // Console.WriteLine(" {0} {1}", i, x); } return(x); }