Made mantissa be stored in a ulong instead of double to prevent accumulating numeric error.
Added case where if the negative exponent is less than 23 to divide from the positive exponents array to pass unit tests.
This commit is contained in:
@@ -61,7 +61,7 @@ namespace Newtonsoft.Json.Tests.Utilities
|
||||
{
|
||||
Assert.AreEqual(expectedValue.Value, d, "Input string: " + s);
|
||||
|
||||
Assert.AreEqual(expectedValue, d2, "DoubleTryParse result is not equal to double.Parse. Input string: " + s);
|
||||
Assert.AreEqual(expectedValue.Value, d2, "DoubleTryParse result is not equal to double.Parse. Input string: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,8 @@ namespace Newtonsoft.Json.Tests.Utilities
|
||||
AssertDoubleTryParse("1", ParseResult.Success, 1);
|
||||
AssertDoubleTryParse("1.2", ParseResult.Success, 1.2);
|
||||
|
||||
AssertDoubleTryParse("1E-21", ParseResult.Success, 1E-21);
|
||||
AssertDoubleTryParse("1E-22", ParseResult.Success, 1E-22);
|
||||
AssertDoubleTryParse("1E-23", ParseResult.Success, 1E-23);
|
||||
AssertDoubleTryParse("1E-25", ParseResult.Success, 1E-25);
|
||||
AssertDoubleTryParse("1E-50", ParseResult.Success, 1E-50);
|
||||
|
||||
@@ -998,10 +998,13 @@ namespace Newtonsoft.Json.Utilities
|
||||
int numDecimalEnd = end;
|
||||
int exponent = 0;
|
||||
bool exponentNegative = false;
|
||||
ulong mantissa = 0UL;
|
||||
int mantissaDigits = 0;
|
||||
int exponentFromMantissa = 0;
|
||||
for (; i < end; i++)
|
||||
{
|
||||
char c = chars[i];
|
||||
switch (chars[i])
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
if (i == start)
|
||||
@@ -1019,87 +1022,89 @@ namespace Newtonsoft.Json.Utilities
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
if (i == start)
|
||||
{
|
||||
if (i == start)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
if (i == numDecimalStart)
|
||||
{
|
||||
// E follows decimal point
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
i++;
|
||||
if (i == end)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
if (i == numDecimalStart)
|
||||
{
|
||||
// E follows decimal point
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
i++;
|
||||
if (i == end)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
if (numDecimalStart < end)
|
||||
{
|
||||
numDecimalEnd = i - 1;
|
||||
}
|
||||
if (numDecimalStart < end)
|
||||
{
|
||||
numDecimalEnd = i - 1;
|
||||
}
|
||||
|
||||
c = chars[i];
|
||||
switch (c)
|
||||
{
|
||||
case '-':
|
||||
exponentNegative = true;
|
||||
i++;
|
||||
break;
|
||||
case '+':
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
|
||||
// parse 3 digit
|
||||
for (;i < end;i++)
|
||||
{
|
||||
c = chars[i];
|
||||
switch (c)
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
case '-':
|
||||
exponentNegative = true;
|
||||
i++;
|
||||
break;
|
||||
case '+':
|
||||
i++;
|
||||
break;
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
// parse 3 digit
|
||||
for (;i < end;i++)
|
||||
{
|
||||
c = chars[i];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
exponent = (10 * exponent) + (c - '0');
|
||||
}
|
||||
|
||||
exponent = (10 * exponent) + (c - '0');
|
||||
}
|
||||
|
||||
if (exponentNegative)
|
||||
if (exponentNegative)
|
||||
{
|
||||
exponent = -exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exponent > MaxExponent)
|
||||
{
|
||||
exponent = -exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exponent > MaxExponent)
|
||||
{
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
value = (10 * value) + (c - '0');
|
||||
break;
|
||||
default:
|
||||
return ParseResult.Invalid;
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
if (mantissaDigits < 19)
|
||||
{
|
||||
mantissa = (10 * mantissa) + (ulong)(c - '0');
|
||||
++mantissaDigits;
|
||||
}
|
||||
else
|
||||
{
|
||||
++exponentFromMantissa;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exponent += exponentFromMantissa;
|
||||
|
||||
// correct the decimal point
|
||||
exponent -= (numDecimalEnd - numDecimalStart);
|
||||
|
||||
if (exponent > 0)
|
||||
{
|
||||
value *= DoubleExponents[exponent - 1];
|
||||
value = mantissa * DoubleExponents[exponent - 1];
|
||||
}
|
||||
else if (exponent < 0)
|
||||
{
|
||||
@@ -1107,17 +1112,25 @@ namespace Newtonsoft.Json.Utilities
|
||||
if (exponent > MaxExponent)
|
||||
{
|
||||
// handle very small numbers, e.g. 4.94065645841247E-324
|
||||
value *= DoubleNegativeExponents[154 - 1];
|
||||
value = mantissa * DoubleNegativeExponents[154 - 1];
|
||||
exponent -= 154;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = mantissa;
|
||||
}
|
||||
|
||||
if (DoubleNegativeExponents.Length <= exponent - 1)
|
||||
{
|
||||
value = 0;
|
||||
return ParseResult.Success;
|
||||
}
|
||||
|
||||
value *= DoubleNegativeExponents[exponent - 1];
|
||||
|
||||
value = exponent < 23 ? value / DoubleExponents[exponent - 1] : value * DoubleNegativeExponents[exponent - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
value = mantissa;
|
||||
}
|
||||
|
||||
if (double.IsPositiveInfinity(value))
|
||||
|
||||
Reference in New Issue
Block a user