Taking a float and adding hundreds of zeros, you may get a truncated value that is just one over the desired value (bug fix) (#1388)
* Found a bug where if take some float and add many zeros, you may get a truncated value that is just one over the desired value.
This commit is contained in:
parent
ce1756425f
commit
7dbe4caf3f
|
@ -98,7 +98,20 @@ decimal parse_decimal(const char *&p) noexcept {
|
|||
}
|
||||
answer.decimal_point = int32_t(first_after_period - p);
|
||||
}
|
||||
|
||||
if(answer.num_digits > 0) {
|
||||
const char *preverse = p - 1;
|
||||
int32_t trailing_zeros = 0;
|
||||
while ((*preverse == '0') || (*preverse == '.')) {
|
||||
if(*preverse == '0') { trailing_zeros++; };
|
||||
--preverse;
|
||||
}
|
||||
answer.decimal_point += int32_t(answer.num_digits);
|
||||
answer.num_digits -= uint32_t(trailing_zeros);
|
||||
}
|
||||
if(answer.num_digits > max_digits ) {
|
||||
answer.num_digits = max_digits;
|
||||
answer.truncated = true;
|
||||
}
|
||||
if (('e' == *p) || ('E' == *p)) {
|
||||
++p;
|
||||
bool neg_exp = false;
|
||||
|
@ -118,11 +131,6 @@ decimal parse_decimal(const char *&p) noexcept {
|
|||
}
|
||||
answer.decimal_point += (neg_exp ? -exp_number : exp_number);
|
||||
}
|
||||
answer.decimal_point += answer.num_digits;
|
||||
if(answer.num_digits > max_digits ) {
|
||||
answer.num_digits = max_digits;
|
||||
answer.truncated = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
|
|
@ -280,6 +280,12 @@ namespace number_tests {
|
|||
std::cout << std::dec;
|
||||
return true;
|
||||
}
|
||||
bool truncated_borderline() {
|
||||
std::cout << __func__ << std::endl;
|
||||
std::string round_to_even = "9007199254740993.0";
|
||||
for(size_t i = 0; i < 1000; i++) { round_to_even += "0"; }
|
||||
return basic_test_64bit(round_to_even,9007199254740992);
|
||||
}
|
||||
|
||||
bool specific_tests() {
|
||||
std::cout << __func__ << std::endl;
|
||||
|
@ -299,7 +305,8 @@ namespace number_tests {
|
|||
}
|
||||
|
||||
bool run() {
|
||||
return specific_tests() &&
|
||||
return truncated_borderline() &&
|
||||
specific_tests() &&
|
||||
ground_truth() &&
|
||||
small_integers() &&
|
||||
powers_of_two() &&
|
||||
|
|
|
@ -119,9 +119,9 @@ bool check_float(double result, const char *buf) {
|
|||
return false;
|
||||
}
|
||||
if (expected != result) {
|
||||
fprintf(stderr, "parsed %.128e from \n", result);
|
||||
fprintf(stderr, " %.32s whereas strtod gives\n", buf);
|
||||
fprintf(stderr, " %.128e,", expected);
|
||||
std::cerr << std::hexfloat << " parsed " << result << " from "
|
||||
<< buf << " whereas strtod gives " << expected << std::endl;
|
||||
std::cerr << std::defaultfloat;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue