From a63ee1b323db342de1277dede28ad1c057639a15 Mon Sep 17 00:00:00 2001 From: Antony Dovgal Date: Thu, 19 Apr 2007 09:30:10 +0000 Subject: [PATCH] fix & unify double-to-string conversion utils --- Zend/tests/double_to_string.phpt | 66 ++++++++++++++++++++++++++++++++ Zend/zend_operators.c | 20 ++++++++-- Zend/zend_strtod.c | 9 ++++- 3 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/double_to_string.phpt diff --git a/Zend/tests/double_to_string.phpt b/Zend/tests/double_to_string.phpt new file mode 100644 index 0000000000..461c03fc8e --- /dev/null +++ b/Zend/tests/double_to_string.phpt @@ -0,0 +1,66 @@ +--TEST-- +double to string conversion tests +--FILE-- + +--EXPECTF-- +string(7) "2.9E+17" +string(7) "2.9E+14" +string(14) "29000000000000" +string(14) "29000000000000" +string(14) "29000000000001" +string(13) "29000.7123123" +string(15) "239234242.71231" +string(16) "0.12345678901235" +string(14) "10000000000000" +string(7) "1.0E+14" +string(7) "1.0E+18" +string(7) "1.0E+14" +string(11) "10000000000" +string(7) "1.0E+15" +string(7) "1.0E+16" +string(1) "0" +Done +--UEXPECTF-- +unicode(7) "2.9E+17" +unicode(7) "2.9E+14" +unicode(14) "29000000000000" +unicode(14) "29000000000000" +unicode(14) "29000000000001" +unicode(13) "29000.7123123" +unicode(15) "239234242.71231" +unicode(16) "0.12345678901235" +unicode(14) "10000000000000" +unicode(7) "1.0E+14" +unicode(7) "1.0E+18" +unicode(7) "1.0E+14" +unicode(11) "10000000000" +unicode(7) "1.0E+15" +unicode(7) "1.0E+16" +unicode(1) "0" +Done diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 58bf8f6ebb..8b142e6286 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -769,10 +769,24 @@ static UChar* zend_u_format_gdouble(double dnum, int ndigit, UChar *result) p1 = zend_u_format_double(dnum, ndigit, &decpt, &sign, 1, buf1); p2 = result; - if (sign) + + if (sign) { *p2++ = (UChar) 0x2d /*'-'*/; - for (i = ndigit - 1; i > 0 && p1[i] == (UChar) 0x30 /*'0'*/; i--) - ndigit--; + } + /* if decimal point position is less than precision, cut zeros only in fractional part */ + if (decpt <= ndigit) { + i = ndigit - 1; + while (i > 0 && i >= decpt && p1[i] == (UChar) 0x30 /*'0'*/) { + ndigit--; + i--; + } + } else { + /* otherwise cut all trailing zeros */ + for (i = ndigit - 1; i > 0 && p1[i] == (UChar) 0x30 /*'0'*/; i--) { + ndigit--; + } + } + if ((decpt >= 0 && decpt - ndigit > 4) || (decpt < 0 && decpt < -3)) { /* use E-style */ decpt--; diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 0328416dfe..23dd743ef9 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -1719,7 +1719,14 @@ ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, int *sig if (value(d) > 0.5 + value(eps)) goto bump_up; else if (value(d) < 0.5 - value(eps)) { - while(*--s == '0'); + /* cut ALL traling zeros only if the number of chars is greater than precision + * otherwise cut only extra zeros + */ + if (k < ndigits) { + while(*--s == '0' && (s - s0) > k); + } else { + while(*--s == '0'); + } s++; goto ret1; } -- 2.50.1