Преглед изворни кода

Never use exponential display for Numbers with radix not 10 (Fix #3739,#3740)

Other engines (SpiderMonkey, JSC and V8) never use exponential display for
num.toString(radix) if radix is not 10, no matter how large num is. This PR
updates the code and the test cases to match that behavior.

This PR fixes #3739 and #3740.

Related issues: #2751, #3635.
Xiaoyin Liu пре 8 година
родитељ
комит
4c8fc73090
3 измењених фајлова са 48 додато и 117 уклоњено
  1. 0 117
      lib/Common/Common/NumberUtilities_strtod.cpp
  2. 2 0
      test/Number/toString.js
  3. 46 0
      test/Number/toString_3.baseline

+ 0 - 117
lib/Common/Common/NumberUtilities_strtod.cpp

@@ -2528,123 +2528,6 @@ BOOL Js::NumberUtilities::FNonZeroFiniteDblToStr(double dbl, _In_range_(2, 36) i
     maxOutDigits = g_rgcchSig[radix];
     __analysis_assume(maxOutDigits > 0);
 
-    if (dbl < 1e-21 || dbl > 1e+21)
-    {
-        // Use exponential notation. Get the exponent and normalize.
-        if (cbitDigit != 0)
-        {
-            // Power of 2. These computations are exact.
-            wExp = wExp2 / cbitDigit;
-            wExp2 = wExp * cbitDigit;
-
-            // Avoid overflow and underflow.
-            if (wExp2 > 0)
-            {
-                wExp2 -= cbitDigit;
-                dbl /= radix;
-            }
-            else
-            {
-                wExp2 += cbitDigit;
-                dbl *= radix;
-            }
-
-            Js::NumberUtilities::LuHiDbl(valueT) = (uint32)(0x03FF + wExp2) << 20;
-            Js::NumberUtilities::LuLoDbl(valueT) = 0;
-        }
-        else
-        {
-            wExp = (int)floor(log(dbl) / log((double)radix) + 1.0);
-            valueT = pow((double)radix, wExp);
-            if (!Js::NumberUtilities::IsFinite(valueT))
-            {
-                valueT = pow((double)radix, --wExp);
-            }
-            else if (0 == valueT)
-            {
-                valueT = pow((double)radix, ++wExp);
-            }
-        }
-        dbl = dbl / valueT;
-
-        while (dbl < 1)
-        {
-            dbl *= radix;
-            wExp--;
-        }
-        AssertMsg(1 <= dbl && dbl < radix, "malformed computation in radix toString()");
-
-        // First digit.
-        wDig = (int)dbl;
-        if (len < 2)
-        {
-            return FALSE; //We run out of buffer size.
-        }
-        len--;
-        *ppsz++ = ToDigit(wDig);
-        maxOutDigits--;
-        dbl -= wDig;
-
-        // Radix point and remaining digits.
-        if (0 != dbl)
-        {
-            if (len < maxOutDigits + 2)
-            {
-                return FALSE; //We run out of buffer size.
-            }
-            len -= maxOutDigits + 1;
-            *ppsz++ = '.';
-            while (dbl != 0 && maxOutDigits-- > 0)
-            {
-                dbl *= radix;
-                wDig = (int)dbl;
-                if (wDig >= radix)
-                {
-                    wDig = radix - 1;
-                }
-                *ppsz++ = ToDigit(wDig);
-                dbl -= wDig;
-            }
-        }
-
-        // Exponent.
-        if (len < 9) // NOTE: may actually need less room
-        {
-            return FALSE; //We run out of buffer size.
-        }
-        *ppsz++ = '(';
-        *ppsz++ = 'e';
-        if (wExp < 0)
-        {
-            *ppsz++ = '-';
-            wExp = -wExp;
-        }
-        else
-        {
-            *ppsz++ = '+';
-        }
-        if (wExp >= 10)
-        {
-            if (wExp >= 100)
-            {
-                if (wExp >= 1000)
-                {
-                    *ppsz++ = (char16)('0' + wExp / 1000);
-                    wExp %= 1000;
-                }
-                *ppsz++ = (char16)('0' + wExp / 100);
-                wExp %= 100;
-            }
-            *ppsz++ = (char16)('0' + wExp / 10);
-            wExp %= 10;
-        }
-        *ppsz++ = (char16)('0' + wExp);
-        *ppsz++ = ')';
-        *ppsz = 0;
-
-        return TRUE;
-    }
-
     // Output the integer portion.
     if (1 <= dbl)
     {

+ 2 - 0
test/Number/toString.js

@@ -8,7 +8,9 @@ runTest('new Number(-444123)');
 runTest('new Number("444" + "123.789123456789875436")');
 runTest('new Number(-444123.78963636363636363636)');
 runTest('new Number(0)');
+runTest('0.9999999999999999e21');
 runTest('1e21');
+runTest('1.0000000000000001e21');
 
 function runTest(numberToTestAsString)
 {

+ 46 - 0
test/Number/toString_3.baseline

@@ -113,6 +113,29 @@ n.toPrecision(2):  0.0
 n.toPrecision(5):  0.0000
 n.toPrecision(20):  0.0000000000000000000
 
+Test: 0.9999999999999999e21
+n.toString():  999999999999999900000
+n.toString(10):  999999999999999900000
+n.toString(8):  154327115334273647400000
+n.toString(2):  1101100011010111001001101011011100010111011110100111100000000000000000
+n.toString(16):  3635c9adc5de9e0000
+n.toString(25):  11l259oooooofl0h
+n.toFixed():  999999999999999900000
+n.toFixed(0):  999999999999999900000
+n.toFixed(2):  999999999999999900000.00
+n.toFixed(5):  999999999999999900000.00000
+n.toFixed(20):  999999999999999900000.00000000000000000000
+RangeError: The number of fractional digits is out of range
+RangeError: The number of fractional digits is out of range
+n.toExponential():  9.999999999999999e+20
+n.toExponential(undefined):  9.999999999999999e+20
+n.toExponential(2):  1.00e+21
+n.toExponential(5):  1.00000e+21
+n.toPrecision():  999999999999999900000
+n.toPrecision(2):  1.0e+21
+n.toPrecision(5):  1.0000e+21
+n.toPrecision(20):  9.9999999999999990000e+20
+
 Test: 1e21
 n.toString():  1e+21
 n.toString(10):  1e+21
@@ -136,3 +159,26 @@ n.toPrecision(2):  1.0e+21
 n.toPrecision(5):  1.0000e+21
 n.toPrecision(20):  1.0000000000000000000e+21
 
+Test: 1.0000000000000001e21
+n.toString():  1.0000000000000001e+21
+n.toString(10):  1.0000000000000001e+21
+n.toString(8):  154327115334273650400000
+n.toString(2):  1101100011010111001001101011011100010111011110101000100000000000000000
+n.toString(16):  3635c9adc5dea20000
+n.toString(25):  11l25a0000007fbb
+n.toFixed():  1.0000000000000001e+21
+n.toFixed(0):  1.0000000000000001e+21
+n.toFixed(2):  1.0000000000000001e+21
+n.toFixed(5):  1.0000000000000001e+21
+n.toFixed(20):  1.0000000000000001e+21
+RangeError: The number of fractional digits is out of range
+RangeError: The number of fractional digits is out of range
+n.toExponential():  1.0000000000000001e+21
+n.toExponential(undefined):  1.0000000000000001e+21
+n.toExponential(2):  1.00e+21
+n.toExponential(5):  1.00000e+21
+n.toPrecision():  1.0000000000000001e+21
+n.toPrecision(2):  1.0e+21
+n.toPrecision(5):  1.0000e+21
+n.toPrecision(20):  1.0000000000000001000e+21
+