sc/source/core/tool/interpr2.cxx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
New commits: commit 397d12997a604730ad11316faa34cefd470ee0ff Author: Eike Rathke <er...@redhat.com> AuthorDate: Sat Apr 15 01:01:58 2023 +0200 Commit: Eike Rathke <er...@redhat.com> CommitDate: Sat Apr 15 03:40:24 2023 +0200 ROUNDSIG() Avoid inaccuracy of pow(10,negative) tdf#138220, tdf#105931 follow https://bugs.documentfoundation.org/show_bug.cgi?id=138220#c6 (otherwise unrelated) has an example of =RAWSUBTRACT(ROUNDSIG(-999.13;12);-999.13) resulting in -0,00000000000011368684 instead of 0, due to these 0.1 ... inexact negative power of 10 values. Change-Id: I82429f0871f1de35a7f2092708fc6b9c2e902999 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150438 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Jenkins diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index b8fe537ef3f9..58b3008319ca 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -1002,8 +1002,21 @@ void ScInterpreter::ScRoundUp() void ScInterpreter::RoundSignificant( double fX, double fDigits, double &fRes ) { - double fTemp = ::rtl::math::approxFloor( log10( std::abs(fX) ) ) + 1.0 - fDigits; - fRes = ::rtl::math::round( pow(10.0, -fTemp ) * fX ) * pow( 10.0, fTemp ); + double fTemp = floor( log10( std::abs(fX) ) ) + 1.0 - fDigits; + double fIn = fX; + // Avoid inaccuracy of negative powers of 10. + if (fTemp < 0.0) + fIn *= pow(10.0, -fTemp); + else + fIn /= pow(10.0, fTemp); + // For very large fX there might be an overflow in fIn resulting in + // non-finite. rtl::math::round() handles that and it will be propagated as + // usual. + fRes = ::rtl::math::round(fIn); + if (fTemp < 0.0) + fRes /= pow(10.0, -fTemp); + else + fRes *= pow(10.0, fTemp); } // tdf#105931