/** * @see http://stackoverflow.com/questions/4657468/fast-fixed-point-pow-log-exp-and-sqrt * @see http://www.convict.lu/Jeunes/ultimate_stuff/exp_ln_2.htm * @see http://www.netlib.org/cephes/qlibdoc.html#qlog * @see https://en.wikipedia.org/wiki/Logarithm * Get the logarithm function of the current function. * @param number $precision the max number of decimals. * @return BigNumber this number base 10 log. */ public function Ln($precision = self::BIGNUMBER_DEFAULT_PRECISION) { // sanity checks if ($this->IsNeg()) { $this->_Copy(new BigNumber("NaN")); return $this->PerformPostOperations($precision); } // if this is 1 then log 1 is zero. if ($this->Compare(BigNumberConstants::One()) == 0) { $this->_Copy(BigNumberConstants::Zero()); return $this->PerformPostOperations($precision); } // @see https://www.quora.com/How-can-we-calculate-the-logarithms-by-hand-without-using-any-calculatorhttps://www.quora.com/How-can-we-calculate-the-logarithms-by-hand-without-using-any-calculator // @see https://www.mathsisfun.com/algebra/logarithms.html $counter1 = 0; $counter2 = 0; $counter8 = 0; while ($this->Compare(0.8) < 0) { $this->Mul(1.8, BigNumberConstants::PrecisionPadding($precision)); ++$counter8; } while ($this->Compare(BigNumberConstants::Two()) > 0) { $this->Div(BigNumberConstants::Two(), BigNumberConstants::PrecisionPadding($precision)); ++$counter2; } while ($this->Compare(1.1) > 0) { $this->Div(1.1, BigNumberConstants::PrecisionPadding($precision)); ++$counter1; } // we must make sure that *is $base = BigNumber($this)->Sub(BigNumberConstants::One()); // Base of the numerator; exponent will be explicit $den = BigNumberConstants::One(); // Denominator of the nth term $neg = false; // start positive. // (x-1)^2 (x-1)^3 (x-1)^4 // ln(x) = (x-1) - --------- + ------- - ------- ... // 2 3 4 $result = new BigNumber($base); // Kick it off $baseRaised = new BigNumber($base); for ($i = 0; $i < self::BIGNUMBER_MAX_LN_ITERATIONS; ++$i) { // next denominator $den->Add(BigNumberConstants::One()); // swap operation $neg = !$neg; // the denominator+power is the same thing $baseRaised->Mul($base, BigNumberConstants::PrecisionPadding($precision)); // now divide it $currentBase = BigNumber($baseRaised)->Div($den, BigNumberConstants::PrecisionPadding($precision)); // there is no need to go further, with this precision // and with this number of iterations we will keep adding/subtracting zeros. if ($currentBase->IsZero()) { break; } // and add it/subtract it from the result. if ($neg) { $result->Sub($currentBase); } else { $result->Add($currentBase); } } // log rules are... ln(ab) = ln(a) + ln(b) if ($counter1 > 0) { // "0.0953101798043248600439521232807650922206053653086441991852398081630010142358842328390575029130364930727479418458517498888460436935129806386890150217023263755687346983551204157456607731117050481406611584967219092627683199972666804124629171163211396201386277872575289851216418802049468841988934550053918259553296705084248072320206243393647990631942365020716424972582488628309770740635849277971589257686851592941134955982468458204470563781108676951416362518738052421687452698243540081779470585025890580291528650263570516836272082869034439007178525831485094480503205465208833580782304569935437696233763597527612962802333" $ln11 = new BigNumber([3, 3, 3, 2, 0, 8, 2, 6, 9, 2, 1, 6, 7, 2, 5, 7, 9, 5, 3, 6, 7, 3, 3, 2, 6, 9, 6, 7, 3, 4, 5, 3, 9, 9, 6, 5, 4, 0, 3, 2, 8, 7, 0, 8, 5, 3, 3, 8, 8, 0, 2, 5, 6, 4, 5, 0, 2, 3, 0, 5, 0, 8, 4, 4, 9, 0, 5, 8, 4, 1, 3, 8, 5, 2, 5, 8, 7, 1, 7, 0, 0, 9, 3, 4, 4, 3, 0, 9, 6, 8, 2, 8, 0, 2, 7, 2, 6, 3, 8, 6, 1, 5, 0, 7, 5, 3, 6, 2, 0, 5, 6, 8, 2, 5, 1, 9, 2, 0, 8, 5, 0, 9, 8, 5, 2, 0, 5, 8, 5, 0, 7, 4, 9, 7, 7, 1, 8, 0, 0, 4, 5, 3, 4, 2, 8, 9, 6, 2, 5, 4, 7, 8, 6, 1, 2, 4, 2, 5, 0, 8, 3, 7, 8, 1, 5, 2, 6, 3, 6, 1, 4, 1, 5, 9, 6, 7, 6, 8, 0, 1, 1, 8, 7, 3, 6, 5, 0, 7, 4, 4, 0, 2, 8, 5, 4, 8, 6, 4, 2, 8, 9, 5, 5, 9, 4, 3, 1, 1, 4, 9, 2, 9, 5, 1, 5, 8, 6, 8, 6, 7, 5, 2, 9, 8, 5, 1, 7, 9, 7, 7, 2, 9, 4, 8, 5, 3, 6, 0, 4, 7, 0, 7, 7, 9, 0, 3, 8, 2, 6, 8, 8, 4, 2, 8, 5, 2, 7, 9, 4, 2, 4, 6, 1, 7, 0, 2, 0, 5, 6, 3, 2, 4, 9, 1, 3, 6, 0, 9, 9, 7, 4, 6, 3, 9, 3, 3, 4, 2, 6, 0, 2, 0, 2, 3, 2, 7, 0, 8, 4, 2, 4, 8, 0, 5, 0, 7, 6, 9, 2, 3, 5, 5, 9, 5, 2, 8, 1, 9, 3, 5, 0, 0, 5, 5, 4, 3, 9, 8, 8, 9, 1, 4, 8, 8, 6, 4, 9, 4, 0, 2, 0, 8, 8, 1, 4, 6, 1, 2, 1, 5, 8, 9, 8, 2, 5, 7, 5, 2, 7, 8, 7, 7, 2, 6, 8, 3, 1, 0, 2, 6, 9, 3, 1, 1, 2, 3, 6, 1, 1, 7, 1, 9, 2, 6, 4, 2, 1, 4, 0, 8, 6, 6, 6, 2, 7, 9, 9, 9, 1, 3, 8, 6, 7, 2, 6, 2, 9, 0, 9, 1, 2, 7, 6, 9, 4, 8, 5, 1, 1, 6, 6, 0, 4, 1, 8, 4, 0, 5, 0, 7, 1, 1, 1, 3, 7, 7, 0, 6, 6, 5, 4, 7, 5, 1, 4, 0, 2, 1, 5, 5, 3, 8, 9, 6, 4, 3, 7, 8, 6, 5, 5, 7, 3, 6, 2, 3, 2, 0, 7, 1, 2, 0, 5, 1, 0, 9, 8, 6, 8, 3, 6, 0, 8, 9, 2, 1, 5, 3, 9, 6, 3, 4, 0, 6, 4, 8, 8, 8, 8, 9, 4, 7, 1, 5, 8, 5, 4, 8, 1, 4, 9, 7, 4, 7, 2, 7, 0, 3, 9, 4, 6, 3, 0, 3, 1, 9, 2, 0, 5, 7, 5, 0, 9, 3, 8, 2, 3, 2, 4, 8, 8, 5, 3, 2, 4, 1, 0, 1, 0, 0, 3, 6, 1, 8, 0, 8, 9, 3, 2, 5, 8, 1, 9, 9, 1, 4, 4, 6, 8, 0, 3, 5, 6, 3, 5, 0, 6, 0, 2, 2, 2, 9, 0, 5, 6, 7, 0, 8, 2, 3, 2, 1, 2, 5, 9, 3, 4, 0, 0, 6, 8, 4, 2, 3, 4, 0, 8, 9, 7, 1, 0, 1, 3, 5, 9, 0, 0], 616, false); $ln11->Mul($counter1, BigNumberConstants::PrecisionPadding($precision)); $result->Add($ln11); } // log rules are... ln(ab) = ln(a) + ln(b) if ($counter2 > 0) { // "0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687542001481020570685733685520235758130557032670751635075961930727570828371435190307038623891673471123350115364497955239120475172681574932065155524734139525882950453007095326366642654104239157814952043740430385500801944170641671518644712839968171784546957026271631064546150257207402481637773389638550695260668341137273873722928956493547025762652098859693201965058554764703306793654432547632744951250406069438147104689946506220167720424524529612687946546193165174681392672504103802546259656869144192871608293803172714368" $ln2 = new BigNumber([8, 6, 3, 4, 1, 7, 2, 7, 1, 3, 0, 8, 3, 9, 2, 8, 0, 6, 1, 7, 8, 2, 9, 1, 4, 4, 1, 9, 6, 8, 6, 5, 6, 9, 5, 2, 6, 4, 5, 2, 0, 8, 3, 0, 1, 4, 0, 5, 2, 7, 6, 2, 9, 3, 1, 8, 6, 4, 7, 1, 5, 6, 1, 3, 9, 1, 6, 4, 5, 6, 4, 9, 7, 8, 6, 2, 1, 6, 9, 2, 5, 4, 2, 5, 4, 2, 4, 0, 2, 7, 7, 6, 1, 0, 2, 2, 6, 0, 5, 6, 4, 9, 9, 8, 6, 4, 0, 1, 7, 4, 1, 8, 3, 4, 9, 6, 0, 6, 0, 4, 0, 5, 2, 1, 5, 9, 4, 4, 7, 2, 3, 6, 7, 4, 5, 2, 3, 4, 4, 5, 6, 3, 9, 7, 6, 0, 3, 3, 0, 7, 4, 6, 7, 4, 5, 5, 8, 5, 0, 5, 6, 9, 1, 0, 2, 3, 9, 6, 9, 5, 8, 8, 9, 0, 2, 5, 6, 2, 6, 7, 5, 2, 0, 7, 4, 5, 3, 9, 4, 6, 5, 9, 8, 2, 9, 2, 2, 7, 3, 7, 8, 3, 7, 2, 7, 3, 1, 1, 4, 3, 8, 6, 6, 0, 6, 2, 5, 9, 6, 0, 5, 5, 8, 3, 6, 9, 8, 3, 3, 7, 7, 7, 3, 6, 1, 8, 4, 2, 0, 4, 7, 0, 2, 7, 5, 2, 0, 5, 1, 6, 4, 5, 4, 6, 0, 1, 3, 6, 1, 7, 2, 6, 2, 0, 7, 5, 9, 6, 4, 5, 4, 8, 7, 1, 7, 1, 8, 6, 9, 9, 3, 8, 2, 1, 7, 4, 4, 6, 8, 1, 5, 1, 7, 6, 1, 4, 6, 0, 7, 1, 4, 4, 9, 1, 0, 8, 0, 0, 5, 5, 8, 3, 0, 3, 4, 0, 4, 7, 3, 4, 0, 2, 5, 9, 4, 1, 8, 7, 5, 1, 9, 3, 2, 4, 0, 1, 4, 5, 6, 2, 4, 6, 6, 6, 3, 6, 2, 3, 5, 9, 0, 7, 0, 0, 3, 5, 4, 0, 5, 9, 2, 8, 8, 5, 2, 5, 9, 3, 1, 4, 3, 7, 4, 2, 5, 5, 5, 1, 5, 6, 0, 2, 3, 9, 4, 7, 5, 1, 8, 6, 2, 7, 1, 5, 7, 4, 0, 2, 1, 9, 3, 2, 5, 5, 9, 7, 9, 4, 4, 6, 3, 5, 1, 1, 0, 5, 3, 3, 2, 1, 1, 7, 4, 3, 7, 6, 1, 9, 8, 3, 2, 6, 8, 3, 0, 7, 0, 3, 0, 9, 1, 5, 3, 4, 1, 7, 3, 8, 2, 8, 0, 7, 5, 7, 2, 7, 0, 3, 9, 1, 6, 9, 5, 7, 0, 5, 3, 6, 1, 5, 7, 0, 7, 6, 2, 3, 0, 7, 5, 5, 0, 3, 1, 8, 5, 7, 5, 3, 2, 0, 2, 5, 5, 8, 6, 3, 3, 7, 5, 8, 6, 0, 7, 5, 0, 2, 0, 1, 8, 4, 1, 0, 0, 2, 4, 5, 7, 8, 6, 8, 1, 4, 6, 9, 9, 6, 2, 3, 3, 6, 8, 5, 0, 6, 5, 1, 7, 4, 9, 6, 9, 6, 9, 1, 2, 6, 3, 9, 3, 3, 9, 4, 9, 0, 0, 0, 8, 6, 0, 2, 1, 4, 5, 2, 5, 5, 2, 0, 6, 3, 4, 3, 1, 0, 0, 5, 5, 7, 0, 8, 6, 5, 6, 7, 1, 8, 5, 4, 1, 2, 1, 2, 3, 2, 7, 1, 4, 9, 0, 3, 5, 4, 9, 9, 5, 5, 0, 8, 1, 7, 4, 1, 3, 9, 6, 0], 615, false); $ln2->Mul($counter2, BigNumberConstants::PrecisionPadding($precision)); $result->Add($ln2); } // log rules are... ln(ab) = ln(a) + ln(b) if ($counter8 > 0) { // "0.587786664902119008189731140618863769769379761376981181556740775800809598729560169117097631534284566775973755110200168585012003222536363442471987124070849093654145900869579488705254541486380394750214985439990943264901458147307801981343725602329350916457819213072437061657645370725998495814483186568232484236059984884946504043108616216273293809193522251042201711480828917893925532893803444719889512011504399314051421418444171441064659998892289089035003091141787128108024952008593307276614322356640449112819566260840792601819695518817384830430694637551056654910817069372465364862878039189497360001395678426943344493527" $ln18 = new BigNumber([7, 2, 5, 3, 9, 4, 4, 4, 3, 3, 4, 9, 6, 2, 4, 8, 7, 6, 5, 9, 3, 1, 0, 0, 0, 6, 3, 7, 9, 4, 9, 8, 1, 9, 3, 0, 8, 7, 8, 2, 6, 8, 4, 6, 3, 5, 6, 4, 2, 7, 3, 9, 6, 0, 7, 1, 8, 0, 1, 9, 4, 5, 6, 6, 5, 0, 1, 5, 5, 7, 3, 6, 4, 9, 6, 0, 3, 4, 0, 3, 8, 4, 8, 3, 7, 1, 8, 8, 1, 5, 5, 9, 6, 9, 1, 8, 1, 0, 6, 2, 9, 7, 0, 4, 8, 0, 6, 2, 6, 6, 5, 9, 1, 8, 2, 1, 1, 9, 4, 4, 0, 4, 6, 6, 5, 3, 2, 2, 3, 4, 1, 6, 6, 7, 2, 7, 0, 3, 3, 9, 5, 8, 0, 0, 2, 5, 9, 4, 2, 0, 8, 0, 1, 8, 2, 1, 7, 8, 7, 1, 4, 1, 1, 9, 0, 3, 0, 0, 5, 3, 0, 9, 8, 0, 9, 8, 2, 2, 9, 8, 8, 9, 9, 9, 5, 6, 4, 6, 0, 1, 4, 4, 1, 7, 1, 4, 4, 4, 8, 1, 4, 1, 2, 4, 1, 5, 0, 4, 1, 3, 9, 9, 3, 4, 0, 5, 1, 1, 0, 2, 1, 5, 9, 8, 8, 9, 1, 7, 4, 4, 4, 3, 0, 8, 3, 9, 8, 2, 3, 5, 5, 2, 9, 3, 9, 8, 7, 1, 9, 8, 2, 8, 0, 8, 4, 1, 1, 7, 1, 0, 2, 2, 4, 0, 1, 5, 2, 2, 2, 5, 3, 9, 1, 9, 0, 8, 3, 9, 2, 3, 7, 2, 6, 1, 2, 6, 1, 6, 8, 0, 1, 3, 4, 0, 4, 0, 5, 6, 4, 9, 4, 8, 8, 4, 8, 9, 9, 5, 0, 6, 3, 2, 4, 8, 4, 2, 3, 2, 8, 6, 5, 6, 8, 1, 3, 8, 4, 4, 1, 8, 5, 9, 4, 8, 9, 9, 5, 2, 7, 0, 7, 3, 5, 4, 6, 7, 5, 6, 1, 6, 0, 7, 3, 4, 2, 7, 0, 3, 1, 2, 9, 1, 8, 7, 5, 4, 6, 1, 9, 0, 5, 3, 9, 2, 3, 2, 0, 6, 5, 2, 7, 3, 4, 3, 1, 8, 9, 1, 0, 8, 7, 0, 3, 7, 4, 1, 8, 5, 4, 1, 0, 9, 4, 6, 2, 3, 4, 9, 0, 9, 9, 9, 3, 4, 5, 8, 9, 4, 1, 2, 0, 5, 7, 4, 9, 3, 0, 8, 3, 6, 8, 4, 1, 4, 5, 4, 5, 2, 5, 0, 7, 8, 8, 4, 9, 7, 5, 9, 6, 8, 0, 0, 9, 5, 4, 1, 4, 5, 6, 3, 9, 0, 9, 4, 8, 0, 7, 0, 4, 2, 1, 7, 8, 9, 1, 7, 4, 2, 4, 4, 3, 6, 3, 6, 3, 5, 2, 2, 2, 3, 0, 0, 2, 1, 0, 5, 8, 5, 8, 6, 1, 0, 0, 2, 0, 1, 1, 5, 5, 7, 3, 7, 9, 5, 7, 7, 6, 6, 5, 4, 8, 2, 4, 3, 5, 1, 3, 6, 7, 9, 0, 7, 1, 1, 9, 6, 1, 0, 6, 5, 9, 2, 7, 8, 9, 5, 9, 0, 8, 0, 0, 8, 5, 7, 7, 0, 4, 7, 6, 5, 5, 1, 8, 1, 1, 8, 9, 6, 7, 3, 1, 6, 7, 9, 7, 3, 9, 6, 7, 9, 6, 7, 3, 6, 8, 8, 1, 6, 0, 4, 1, 1, 3, 7, 9, 8, 1, 8, 0, 0, 9, 1, 1, 2, 0, 9, 4, 6, 6, 6, 8, 7, 7, 8, 5, 0], 615, false); $ln18->Mul($counter8, BigNumberConstants::PrecisionPadding($precision)); $result->Sub($ln18); } // done $this->_Copy($result); // clean up and done. return $this->PerformPostOperations($precision); }