diff --git a/docs/docs.html b/docs/docs.html
index e4fc228..271a62a 100644
--- a/docs/docs.html
+++ b/docs/docs.html
@@ -508,7 +508,7 @@ var csv = Papa.unparse({
dynamicTyping
- If true, numeric and boolean data will be converted to their type instead of remaining strings. Numeric data must conform to the definition of a decimal literal. European-formatted numbers must have commas and dots swapped. If also accepts an object or a function. If object it's values should be a boolean to indicate if dynamic typing should be applied for each column number (or header name if using headers). If it's a function, it should return a boolean value for each field number (or name if using headers) which will be passed as first argument.
+ If true, numeric and boolean data will be converted to their type instead of remaining strings. Numeric data must conform to the definition of a decimal literal. Numerical values greater than 2^53 or less than -2^53 will not be converted to numbers to preserve precision. European-formatted numbers must have commas and dots swapped. If also accepts an object or a function. If object it's values should be a boolean to indicate if dynamic typing should be applied for each column number (or header name if using headers). If it's a function, it should return a boolean value for each field number (or name if using headers) which will be passed as first argument.
|
diff --git a/papaparse.js b/papaparse.js
index d6d83fd..acf4c95 100755
--- a/papaparse.js
+++ b/papaparse.js
@@ -996,6 +996,8 @@ License: MIT
function ParserHandle(_config)
{
// One goal is to minimize the use of regular expressions...
+ var MAX_FLOAT = Math.pow(2, 53);
+ var MIN_FLOAT = -MAX_FLOAT;
var FLOAT = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i;
var ISO_DATE = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/;
var self = this;
@@ -1123,6 +1125,16 @@ License: MIT
return _config.skipEmptyLines === 'greedy' ? s.join('').trim() === '' : s.length === 1 && s[0].length === 0;
}
+ function testFloat(s) {
+ if (FLOAT.test(s)) {
+ var floatValue = parseFloat(s);
+ if (floatValue > MIN_FLOAT && floatValue < MAX_FLOAT) {
+ return true;
+ }
+ }
+ return false;
+ }
+
function processResults()
{
if (_results && _delimiterError)
@@ -1190,7 +1202,7 @@ License: MIT
return true;
else if (value === 'false' || value === 'FALSE')
return false;
- else if (FLOAT.test(value))
+ else if (testFloat(value))
return parseFloat(value);
else if (ISO_DATE.test(value))
return new Date(value);
diff --git a/tests/test-cases.js b/tests/test-cases.js
index 9d5be3a..81a2dce 100644
--- a/tests/test-cases.js
+++ b/tests/test-cases.js
@@ -815,11 +815,11 @@ var PARSE_TESTS = [
}
},
{
- description: "Dynamic typing converts numeric literals",
- input: '1,2.2,1e3\r\n-4,-4.5,-4e-5\r\n-,5a,5-2',
+ description: "Dynamic typing converts numeric literals and maintains precision",
+ input: '1,2.2,1e3\r\n-4,-4.5,-4e-5\r\n-,5a,5-2\r\n16142028098527942586,9007199254740991,-9007199254740992',
config: { dynamicTyping: true },
expected: {
- data: [[1, 2.2, 1000], [-4, -4.5, -0.00004], ["-", "5a", "5-2"]],
+ data: [[1, 2.2, 1000], [-4, -4.5, -0.00004], ["-", "5a", "5-2"], ["16142028098527942586", 9007199254740991, "-9007199254740992"]],
errors: []
}
},