Parsing floats with 19 significant digits should be fine. (#1191)
* Parsing floats with 19 significant digits should be fine. * Adding more tests with very long mantissa.
This commit is contained in:
parent
da093c1982
commit
8b5a89c136
|
@ -396,7 +396,9 @@ simdjson_really_inline error_code write_float(const uint8_t *const src, bool neg
|
|||
// we could extend our code by using a 128-bit integer instead
|
||||
// of a 64-bit integer. However, this is uncommon in practice.
|
||||
// digit count is off by 1 because of the decimal (assuming there was one).
|
||||
if (simdjson_unlikely(digit_count-1 >= 19 && significant_digits(start_digits, digit_count) >= 19)) {
|
||||
//
|
||||
// 9999999999999999999 < 2**64 so we can accomodate 19 digits.
|
||||
if (simdjson_unlikely(digit_count-1 > 19 && significant_digits(start_digits, digit_count) > 19)) {
|
||||
// Ok, chances are good that we had an overflow!
|
||||
// this is almost never going to get called!!!
|
||||
// we start anew, going slowly!!!
|
||||
|
@ -715,16 +717,16 @@ SIMDJSON_UNUSED simdjson_really_inline simdjson_result<double> parse_double(cons
|
|||
while (parse_digit(*p, i)) { p++; }
|
||||
exponent = -(p - start_decimal_digits);
|
||||
|
||||
// Overflow check. 19 digits (minus the decimal) may be overflow.
|
||||
overflow = p-src-1 >= 19;
|
||||
// Overflow check. More than 19 digits (minus the decimal) may be overflow.
|
||||
overflow = p-src-1 > 19;
|
||||
if (simdjson_unlikely(overflow && leading_zero)) {
|
||||
// Skip leading 0.00000 and see if it still overflows
|
||||
const uint8_t *start_digits = src + 2;
|
||||
while (*start_digits == '0') { start_digits++; }
|
||||
overflow = start_digits-src >= 19;
|
||||
overflow = start_digits-src > 19;
|
||||
}
|
||||
} else {
|
||||
overflow = p-src >= 19;
|
||||
overflow = p-src > 19;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -52,6 +52,44 @@ namespace number_tests {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool nines() {
|
||||
std::cout << __func__ << std::endl;
|
||||
simdjson::dom::parser parser;
|
||||
std::vector<std::pair<std::string, double>> testing = {
|
||||
{"9999999999999999999.0",9999999999999999999.0},
|
||||
{"9999999999999999999",9999999999999999999.},
|
||||
{"999999999999999999.9",999999999999999999.9},
|
||||
{"99999999999999999.99",99999999999999999.99},
|
||||
{"9999999999999999.999",9999999999999999.999},
|
||||
{"999999999999999.9999",999999999999999.9999},
|
||||
{"99999999999999.99999",99999999999999.99999},
|
||||
{"9999999999999.999999",9999999999999.999999},
|
||||
{"999999999999.9999999",999999999999.9999999},
|
||||
{"99999999999.99999999",99999999999.99999999},
|
||||
{"9999999999.999999999",9999999999.999999999},
|
||||
{"999999999.9999999999",999999999.9999999999},
|
||||
{"99999999.99999999999",99999999.99999999999},
|
||||
{"9999999.999999999999",9999999.999999999999},
|
||||
{"999999.9999999999999",999999.9999999999999},
|
||||
{"99999.99999999999999",99999.99999999999999},
|
||||
{"9999.999999999999999",9999.999999999999999},
|
||||
{"999.9999999999999999",999.9999999999999999},
|
||||
{"99.99999999999999999",99.99999999999999999},
|
||||
{"9.999999999999999999",9.999999999999999999},
|
||||
{"0.9999999999999999999",0.9999999999999999999},
|
||||
{"0.09999999999999999999",0.09999999999999999999},
|
||||
};
|
||||
for (std::pair<std::string, double> p : testing) {
|
||||
double actual;
|
||||
ASSERT_SUCCESS(parser.parse(p.first).get(actual));
|
||||
if (actual != p.second) {
|
||||
std::cerr << "JSON '" << p.first << "' parsed to " << actual << " instead of " << p.first << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool powers_of_two() {
|
||||
std::cout << __func__ << std::endl;
|
||||
char buf[1024];
|
||||
|
@ -182,7 +220,8 @@ namespace number_tests {
|
|||
bool run() {
|
||||
return small_integers() &&
|
||||
powers_of_two() &&
|
||||
powers_of_ten();
|
||||
powers_of_ten() &&
|
||||
nines();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue