diff options
author | Regina Henschel <regina@apache.org> | 2015-04-06 15:51:04 +0000 |
---|---|---|
committer | Regina Henschel <regina@apache.org> | 2015-04-06 15:51:04 +0000 |
commit | 85cd072198d9024c20b741c04a20ef99fc9b5910 (patch) | |
tree | 02272790d59461350c068a3e949d83e3650b08ef /scaddins | |
parent | b923454a0922b6767b28c8dc131534b8daf6d96b (diff) |
#i95167 XIRR() function gives Err:502
Patch by: Driss Ben Zoubeir <driss.zoubeir@gmail.com>
Review by: Regina Henschel <rb.henschel@t-online.de>
Notes
Notes:
merged as: 9f1ffa641b67a4359611bb62d147a9a1e09312cd
Diffstat (limited to 'scaddins')
-rw-r--r-- | scaddins/source/analysis/financial.cxx | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/scaddins/source/analysis/financial.cxx b/scaddins/source/analysis/financial.cxx index 706897f14ce1..148a0a59969d 100644 --- a/scaddins/source/analysis/financial.cxx +++ b/scaddins/source/analysis/financial.cxx @@ -545,16 +545,36 @@ double SAL_CALL AnalysisAddIn::getXirr( // Newton's method - try to find a fResultRate, so that lcl_sca_XirrResult() returns 0. double fNewRate, fRateEps, fResultValue; sal_Int32 nIter = 0; - bool bContLoop; + sal_Int32 nIterScan = 0; + bool bContLoop = false; + bool bResultRateScanEnd = false; + + // First the inner while-loop will be executed using the default Value fResultRate + // or the user guessed fResultRate if those do not deliver a solution for the + // Newton's method then the range from -0.99 to +0.99 will be scanned with a + // step size of 0.01 to find fResultRate's value which can deliver a solution do { - fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate ); - fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate ); - fRateEps = fabs( fNewRate - fResultRate ); - fResultRate = fNewRate; - bContLoop = (fRateEps > fMaxEps) && (fabs( fResultValue ) > fMaxEps); + if (nIterScan >=1) + fResultRate = -0.99 + (nIterScan -1)* 0.01; + do + { + fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate ); + fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate ); + fRateEps = fabs( fNewRate - fResultRate ); + fResultRate = fNewRate; + bContLoop = (fRateEps > fMaxEps) && (fabs( fResultValue ) > fMaxEps); + } + while( bContLoop && (++nIter < nMaxIter) ); + nIter = 0; + if ( ::rtl::math::isNan(fResultRate) || ::rtl::math::isInf(fResultRate) + ||::rtl::math::isNan(fResultValue) || ::rtl::math::isInf(fResultValue)) + bContLoop = true; + + ++nIterScan; + bResultRateScanEnd = (nIterScan >= 200); } - while( bContLoop && (++nIter < nMaxIter) ); + while(bContLoop && !bResultRateScanEnd); if( bContLoop ) THROW_IAE; |