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 <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 397d12997a604730ad11316faa34cefd470ee0ff)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150618
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index a0b857de..6259d20 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -1036,8 +1036,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