basic/qa/basic_coverage/test_cstr_method.vb |   43 +++++++
 basic/qa/vba_tests/cstr.vb                  |   10 +
 basic/source/sbx/sbxscan.cxx                |  157 +---------------------------
 3 files changed, 58 insertions(+), 152 deletions(-)

New commits:
commit da0d6541b29f4dd3cd223e15be14dabc2704fb83
Author:     Andreas Heinisch <andreas.heini...@yahoo.de>
AuthorDate: Wed Sep 29 18:19:35 2021 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Sep 30 15:12:56 2021 +0200

    tdf#143575, tdf#143974 - Use rtl::math::doubleToUString to convert numbers 
to strings
    
    Change-Id: I1427dbd49af680a1bf386410977c9cb2b0a3961e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122831
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    Tested-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122880
    Tested-by: Jenkins

diff --git a/basic/qa/basic_coverage/test_cstr_method.vb 
b/basic/qa/basic_coverage/test_cstr_method.vb
index 53484b06fe17..6635bae746be 100644
--- a/basic/qa/basic_coverage/test_cstr_method.vb
+++ b/basic/qa/basic_coverage/test_cstr_method.vb
@@ -6,11 +6,48 @@
 ' file, You can obtain one at http://mozilla.org/MPL/2.0/.
 '
 
-Function doUnitTest as Integer
-    ' CSTR
-    If (CStr(100) <> "100") Then
+Dim passCount As Integer
+Dim failCount As Integer
+Dim result As String
+
+Function doUnitTest() As String
+    result = verify_testCStr()
+    If failCount <> 0 Or passCount = 0 Then
         doUnitTest = 0
     Else
         doUnitTest = 1
     End If
 End Function
+
+Function verify_testCStr() As String
+
+    passCount = 0
+    failCount = 0
+
+    result = "Test Results" & Chr$(10) & "============" & Chr$(10)
+
+    ' CSTR
+    TestLog_ASSERT CStr(100), "100", "CStr(100)"
+
+    ' tdf#143575 - round string to their nearest double representation
+    ' Without the fix in place, this test would have failed with:
+    ' - Expected: 691.2
+    ' - Actual  : 691.2000000000001
+    TestLog_ASSERT CStr(691.2), "691.2", "CStr(691.2)"
+    ' Without the fix in place, this test would have failed with:
+    ' - Expected: 691.2
+    ' - Actual  : 691.1999999999999
+    TestLog_ASSERT CStr(123.4 + 567.8), "691.2", "CStr(123.4 + 567.8)"
+
+    result = result & Chr$(10) & "Tests passed: " & passCount & Chr$(10) & 
"Tests failed: " & failCount & Chr$(10)
+    verify_testCStr = result
+End Function
+
+Sub TestLog_ASSERT(actual As Variant, expected As Variant, testName As String)
+    If expected = actual Then
+        passCount = passCount + 1
+    Else
+        result = result & Chr$(10) & "Failed: " & testName & " returned " & 
actual & ", expected " & expected
+        failCount = failCount + 1
+    End If
+End Sub
diff --git a/basic/qa/vba_tests/cstr.vb b/basic/qa/vba_tests/cstr.vb
index 55e1ab049fab..dfa77b7db1f0 100644
--- a/basic/qa/vba_tests/cstr.vb
+++ b/basic/qa/vba_tests/cstr.vb
@@ -23,6 +23,16 @@ Sub verify_testCStr()
     TestUtil.AssertEqual(CStr(n),   "437.324", "CStr(n)")
     TestUtil.AssertEqual(CStr(500), "500",     "CStr(500)")
 
+    ' tdf#143575 - round string to their nearest double representation
+    ' Without the fix in place, this test would have failed with:
+    ' - Expected: 691.2
+    ' - Actual  : 691.2000000000001
+    TestUtil.AssertEqual(CStr(691.2), "691.2", "CStr(691.2)")
+    ' Without the fix in place, this test would have failed with:
+    ' - Expected: 691.2
+    ' - Actual  : 691.1999999999999
+    TestUtil.AssertEqual(CStr(123.4 + 567.8), "691.2", "CStr(123.4 + 567.8)")
+
     Exit Sub
 errorHandler:
     TestUtil.ReportErrorHandler("verify_testCStr", Err, Error$, Erl)
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index 0a7be60432a7..2d42c2351d4f 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -297,134 +297,6 @@ ErrCode SbxValue::ScanNumIntnl( const OUString& rSrc, 
double& nVal, bool bSingle
     return nRetError;
 }
 
-
-const double roundArray[] = {
-    5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, 0.5e-7,
-    0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,0.5e-15 };
-
-/*
-|*
-|*  void myftoa( double, char *, short, short, bool, bool )
-|*
-|*  description:        conversion double --> ASCII
-|*  parameters:         double              the number
-|*                      char *              target buffer
-|*                      short               number of positions after decimal 
point
-|*                      short               range of the exponent ( 0=no E )
-|*                      bool                true: with 1000-separators
-|*                      bool                true: output without formatting
-|*
- */
-
-static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth )
-{
-
-    short nExp = 0;
-    short nDig = nPrec + 1;
-    short nDec;                         // number of positions before decimal 
point
-    int i;
-
-    sal_Unicode cDecimalSep, cThousandSep, cDecimalSepAlt;
-    ImpGetIntntlSep( cDecimalSep, cThousandSep, cDecimalSepAlt );
-
-    // compute exponent
-    nExp = 0;
-    if( nNum > 0.0 )
-    {
-        while( nNum <   1.0 )
-        {
-            nNum *= 10.0;
-            nExp--;
-        }
-        while( nNum >= 10.0 )
-        {
-            nNum /= 10.0;
-            nExp++;
-        }
-    }
-    if( !nPrec )
-        nDig = nExp + 1;
-
-    // round number
-    if( (nNum += roundArray [std::min<short>( nDig, 16 )] ) >= 10.0 )
-    {
-        nNum = 1.0;
-        ++nExp;
-        if( !nExpWidth ) ++nDig;
-    }
-
-    // determine positions before decimal point
-    if( !nExpWidth )
-    {
-        if( nExp < 0 )
-        {
-            // #41691: also a 0 at bFix
-            *pBuf++ = '0';
-            if( nPrec ) *pBuf++ = static_cast<char>(cDecimalSep);
-            i = -nExp - 1;
-            if( nDig <= 0 ) i = nPrec;
-            while( i-- )    *pBuf++ = '0';
-            nDec = 0;
-        }
-        else
-            nDec = nExp+1;
-    }
-    else
-        nDec = 1;
-
-    // output number
-    if( nDig > 0 )
-    {
-        int digit;
-        for( i = 0 ; ; ++i )
-        {
-            if( i < 16 )
-            {
-                digit = static_cast<int>(nNum);
-                *pBuf++ = sal::static_int_cast< char >(digit + '0');
-                nNum =( nNum - digit ) * 10.0;
-            } else
-                *pBuf++ = '0';
-            if( --nDig == 0 ) break;
-            if( nDec )
-            {
-                nDec--;
-                if( !nDec )
-                    *pBuf++ = static_cast<char>(cDecimalSep);
-            }
-        }
-    }
-
-    // output exponent
-    if( nExpWidth )
-    {
-        if( nExpWidth < 3 ) nExpWidth = 3;
-        nExpWidth -= 2;
-        *pBuf++ = 'E';
-        if ( nExp < 0 )
-        {
-            nExp = -nExp;
-            *pBuf++ = '-';
-        }
-        else
-            *pBuf++ = '+';
-        while( nExpWidth > 3 )
-        {
-            *pBuf++ = '0';
-            nExpWidth--;
-        }
-        if( nExp >= 100 || nExpWidth == 3 )
-        {
-            *pBuf++ = sal::static_int_cast< char >(nExp/100 + '0');
-            nExp %= 100;
-        }
-        if( nExp/10 || nExpWidth >= 2 )
-            *pBuf++ = sal::static_int_cast< char >(nExp/10 + '0');
-        *pBuf++ = sal::static_int_cast< char >(nExp%10 + '0');
-    }
-    *pBuf = 0;
-}
-
 // The number is prepared unformattedly with the given number of
 // NK-positions. A leading minus is added if applicable.
 // This routine is public because it's also used by the Put-functions
@@ -432,32 +304,19 @@ static void myftoa( double nNum, char * pBuf, short 
nPrec, short nExpWidth )
 
 void ImpCvtNum( double nNum, short nPrec, OUString& rRes, bool bCoreString )
 {
-    char *q;
-    char cBuf[ 40 ], *p = cBuf;
-
     sal_Unicode cDecimalSep, cThousandSep, cDecimalSepAlt;
     ImpGetIntntlSep( cDecimalSep, cThousandSep, cDecimalSepAlt );
     if( bCoreString )
         cDecimalSep = '.';
 
-    if( nNum < 0.0 ) {
-        nNum = -nNum;
-        *p++ = '-';
-    }
-    double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14;
-    myftoa( nNum, p, nPrec,( nNum &&( nNum < 1E-1 || nNum >= dMaxNumWithoutExp 
) ) ? 4:0 );
-    // remove trailing zeros
-    for( p = cBuf; *p &&( *p != 'E' ); p++ ) {}
-    q = p; p--;
-    while( nPrec && *p == '0' )
-    {
-        nPrec--;
-        p--;
-    }
-    if( *p == cDecimalSep ) p--;
-    while( *q ) *++p = *q++;
-    *++p = 0;
-    rRes = OUString::createFromAscii( cBuf );
+    const double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14;
+    rtl_math_StringFormat aMathStringFormat
+        = (nNum && (std::abs(nNum) < 1E-1 || std::abs(nNum) >= 
dMaxNumWithoutExp))
+              ? rtl_math_StringFormat_E2
+              : rtl_math_StringFormat_F;
+
+    // tdf#143575 - use rtl::math::doubleToUString to convert numbers to 
strings in basic
+    rRes = rtl::math::doubleToUString(nNum, aMathStringFormat, nPrec, 
cDecimalSep, true);
 }
 
 bool ImpConvStringExt( OUString& rSrc, SbxDataType eTargetType )

Reply via email to