summaryrefslogtreecommitdiffstats
path: root/basic
diff options
context:
space:
mode:
authorAndreas Heinisch <andreas.heinisch@yahoo.de>2021-09-29 18:19:35 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2021-09-30 15:12:56 +0200
commitda0d6541b29f4dd3cd223e15be14dabc2704fb83 (patch)
treedfbff8b800fdca8e4fbfb7600a19a708319b985e /basic
parentRelated: tdf#144139 use the classic size calculation (diff)
downloadcore-da0d6541b29f4dd3cd223e15be14dabc2704fb83.tar.gz
core-da0d6541b29f4dd3cd223e15be14dabc2704fb83.zip
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.kaganski@collabora.com> Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de> Tested-by: Andreas Heinisch <andreas.heinisch@yahoo.de> Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122880 Tested-by: Jenkins
Diffstat (limited to 'basic')
-rw-r--r--basic/qa/basic_coverage/test_cstr_method.vb43
-rw-r--r--basic/qa/vba_tests/cstr.vb10
-rw-r--r--basic/source/sbx/sbxscan.cxx157
3 files changed, 58 insertions, 152 deletions
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 )