Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
[Merge chakra-core/ChakraCore@ee3378557e] [MERGE #3742 @xiaoyinl] Nev…
Browse files Browse the repository at this point in the history
…er use exponential if radix not 10 (Fix #3739, #3740)

Merge pull request #3742 from xiaoyinl:never_use_exp

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 fixes #3740.

See also: #2751, #3635.

/cc @dilijev @littledan @bterlson
  • Loading branch information
chakrabot committed Oct 21, 2017
1 parent 93718f1 commit 1fac205
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 117 deletions.
117 changes: 0 additions & 117 deletions deps/chakrashim/core/lib/Common/Common/NumberUtilities_strtod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions deps/chakrashim/core/test/Number/toString.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
46 changes: 46 additions & 0 deletions deps/chakrashim/core/test/Number/toString_3.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

0 comments on commit 1fac205

Please sign in to comment.