]> granicus.if.org Git - icu/commitdiff
ICU-13177 Adding IntlTest DoubleToUnicodeString and improving DecimalQuantity test
authorShane Carr <shane@unicode.org>
Wed, 27 Sep 2017 22:31:07 +0000 (22:31 +0000)
committerShane Carr <shane@unicode.org>
Wed, 27 Sep 2017 22:31:07 +0000 (22:31 +0000)
X-SVN-Rev: 40486

icu4c/source/i18n/number_decimalquantity.cpp
icu4c/source/test/intltest/intltest.cpp
icu4c/source/test/intltest/intltest.h
icu4c/source/test/intltest/numbertest.h
icu4c/source/test/intltest/numbertest_api.cpp
icu4c/source/test/intltest/numbertest_decimalquantity.cpp

index 3c3a77e0fd6855259896d959e2333db8e59edd6a..b78e83146680e7da6407a2cdb82813ae54763c61 100644 (file)
@@ -387,9 +387,10 @@ void DecimalQuantity::convertToAccurateDouble() {
 
     // Call the slow oracle function (Double.toString in Java, sprintf in C++).
     // The <float.h> constant DBL_DIG defines a platform-specific number of digits in a double.
-    // However, this tends to be too low (see #11318). Instead, we always use 14 digits.
-    char dstr[14 + 8]; // Extra space for '+', '.', e+NNN, and '\0'
-    sprintf(dstr, "%+1.14e", n);
+    // However, this tends to be too low (see #11318). Instead, we always use 14 decimal places.
+    static constexpr size_t CAP = 1 + 14 + 8; // Extra space for '+', '.', e+NNN, and '\0'
+    char dstr[CAP];
+    snprintf(dstr, CAP, "%+1.14e", n);
 
     // uprv_decNumberFromString() will parse the string expecting '.' as a
     // decimal separator, however sprintf() can use ',' in certain locales.
@@ -400,7 +401,8 @@ void DecimalQuantity::convertToAccurateDouble() {
     }
 
     decNumber dn;
-    stringToDecNumber(dstr, dn);
+    StringPiece sp(dstr);
+    stringToDecNumber(sp, dn);
     _setToDecNumber(&dn);
 
     scale += delta;
index 8147bbfdfa9a64bf5d8b462e6a8e39802d2d8c27..b66e6256761d7f1c7d7b355b759106ff0a7a41dc 100644 (file)
@@ -109,6 +109,18 @@ Int64ToUnicodeString(int64_t num)
     return buffer;
 }
 
+UnicodeString
+DoubleToUnicodeString(double num)
+{
+    char buffer[64];    // nos changed from 10 to 64
+    char danger = 'p';  // guard against overrunning the buffer (rtg)
+
+    sprintf(buffer, "%1.14e", num);
+    assert(danger == 'p');
+
+    return buffer;
+}
+
 // [LIU] Just to get things working
 UnicodeString
 operator+(const UnicodeString& left,
index 389b313807fddc74aedea309ff4d7227dd8e1a5a..1f7c80d4794ebc80f8e5e49a3ab443606cf2eac2 100644 (file)
@@ -30,6 +30,7 @@ U_NAMESPACE_USE
 //string-concatenation operator (moved from findword test by rtg)
 UnicodeString UCharToUnicodeString(UChar c);
 UnicodeString Int64ToUnicodeString(int64_t num);
+UnicodeString DoubleToUnicodeString(double num);
 //UnicodeString operator+(const UnicodeString& left, int64_t num); // Some compilers don't allow this because of the long type.
 UnicodeString operator+(const UnicodeString& left, long num);
 UnicodeString operator+(const UnicodeString& left, unsigned long num);
index ec07d9784fdd9579bbd33b7aac1d4a84aac4d8f6..1b8caa04aea79a283ff12372e11220bc108222a2 100644 (file)
@@ -58,6 +58,7 @@ class NumberFormatterApiTest : public IntlTest {
     void sign();
     void decimal();
     void locale();
+    void formatTypes();
     void errors();
 
     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
@@ -101,7 +102,7 @@ class DecimalQuantityTest : public IntlTest {
     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
 
   private:
-    void assertDoubleEquals(const char *message, double a, double b);
+    void assertDoubleEquals(UnicodeString message, double a, double b);
     void assertHealth(const DecimalQuantity &fq);
     void assertToStringAndHealth(const DecimalQuantity &fq, const UnicodeString &expected);
     void checkDoubleBehavior(double d, bool explicitRequired);
index 7ada621824e4a76f458539d369f318ff86ab61cf..ba0f6269d58e7eaee45c33cc0c2c74a3a09c2341 100644 (file)
@@ -70,6 +70,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
         TESTCASE_AUTO(sign);
         TESTCASE_AUTO(decimal);
         TESTCASE_AUTO(locale);
+        TESTCASE_AUTO(formatTypes);
         TESTCASE_AUTO(errors);
     TESTCASE_AUTO_END;
 }
@@ -1402,6 +1403,14 @@ void NumberFormatterApiTest::locale() {
     assertEquals("Locale withLocale()", u"1 234", actual);
 }
 
+void NumberFormatterApiTest::formatTypes() {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalizedNumberFormatter formatter = NumberFormatter::withLocale(Locale::getEnglish());
+    const char* str1 = "98765432123456789E1";
+    UnicodeString actual = formatter.formatDecimal(str1, status).toString();
+    assertEquals("Format decNumber", u"987,654,321,234,567,890", actual);
+}
+
 void NumberFormatterApiTest::errors() {
     LocalizedNumberFormatter lnf = NumberFormatter::withLocale(Locale::getEnglish()).rounding(
             Rounder::fixedFraction(
index d863c58748964a35b37527a0f2e50ecc69c24f19..136d90c7a1acc0b8e3cb9efe705d4ffd5452f883 100644 (file)
@@ -21,7 +21,7 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char *
     TESTCASE_AUTO_END;
 }
 
-void DecimalQuantityTest::assertDoubleEquals(const char *message, double a, double b) {
+void DecimalQuantityTest::assertDoubleEquals(UnicodeString message, double a, double b) {
     if (a == b) {
         return;
     }
@@ -30,7 +30,7 @@ void DecimalQuantityTest::assertDoubleEquals(const char *message, double a, doub
     diff = diff < 0 ? -diff : diff;
     double bound = a < 0 ? -a * 1e-6 : a * 1e-6;
     if (diff > bound) {
-        errln(message);
+        errln(message + u": " + DoubleToUnicodeString(a) + u" vs " + DoubleToUnicodeString(b) + u" differ by " + DoubleToUnicodeString(diff));
     }
 }
 
@@ -54,12 +54,18 @@ void DecimalQuantityTest::checkDoubleBehavior(double d, bool explicitRequired) {
     if (explicitRequired) {
         assertTrue("Should be using approximate double", !fq.isExplicitExactDouble());
     }
-    assertDoubleEquals("Initial construction from hard double", d, fq.toDouble());
+    UnicodeString baseStr = fq.toString();
+    assertDoubleEquals(
+        UnicodeString(u"Initial construction from hard double: ") + baseStr,
+        d, fq.toDouble());
     fq.roundToInfinity();
+    UnicodeString newStr = fq.toString();
     if (explicitRequired) {
         assertTrue("Should not be using approximate double", fq.isExplicitExactDouble());
     }
-    assertDoubleEquals("After conversion to exact BCD (double)", d, fq.toDouble());
+    assertDoubleEquals(
+        UnicodeString(u"After conversion to exact BCD (double): ") + baseStr + u" vs " + newStr,
+        d, fq.toDouble());
 }
 
 void DecimalQuantityTest::testDecimalQuantityBehaviorStandalone() {
@@ -205,11 +211,11 @@ void DecimalQuantityTest::testConvertToAccurateDouble() {
         checkDoubleBehavior(d, false);
     }
 
-    assertDoubleEquals("NaN check failed", NAN, DecimalQuantity().setToDouble(NAN).toDouble());
+    assertDoubleEquals(u"NaN check failed", NAN, DecimalQuantity().setToDouble(NAN).toDouble());
     assertDoubleEquals(
-            "Inf check failed", INFINITY, DecimalQuantity().setToDouble(INFINITY).toDouble());
+            u"Inf check failed", INFINITY, DecimalQuantity().setToDouble(INFINITY).toDouble());
     assertDoubleEquals(
-            "-Inf check failed", -INFINITY, DecimalQuantity().setToDouble(-INFINITY).toDouble());
+            u"-Inf check failed", -INFINITY, DecimalQuantity().setToDouble(-INFINITY).toDouble());
 
     // Generate random doubles
     for (int32_t i = 0; i < 10000; i++) {