ICU-13177 Adding IntlTest DoubleToUnicodeString and improving DecimalQuantity test

X-SVN-Rev: 40486
This commit is contained in:
Shane Carr 2017-09-27 22:31:07 +00:00
parent 511ebeaa92
commit eb34602c75
6 changed files with 43 additions and 12 deletions

View 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;

View 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,

View 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);

View 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);

View 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(

View 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++) {