Can you give to me a 16 digits (or more) decimal number that converted in double precision floating point round correctly only at 15th?
Such numbers are not rare so easy enough to try various strings limited to the range of interest.
Over a wide range of 16 digit decimal text values, about 10% failed. All failures began with a leading digit of '4'
or more - not surprising.
// Although a C++ post, below is some C code
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void form_text_number(char *buf, int significant_digits, int min_expo, int max_expo) {
unsigned i = 0;
buf[i++] = (char) (rand() % 9 + '1');
buf[i++] = '.';
for (int sd = 1; sd < significant_digits; sd++) {
buf[i++] = (char) (rand() % 10 + '0');
}
sprintf(buf + i, "e%+03d", rand() % (max_expo - min_expo + 1) + min_expo);
}
bool round_trip_text_double_text(const char *s, int significant_digits) {
double d = atof(s);
char buf[significant_digits + 10];
sprintf(buf, "%.*e", significant_digits - 1, d);
if (strcmp(s, buf)) {
printf("Round trip failed \"%s\" %.*e \"%s\"\n", s, significant_digits - 1 + 3,d, buf);
return false;
}
return true;
}
Test code
void test_sig(unsigned n, int significant_digits, int min_expo, int max_expo) {
printf("Sig digits %2d: ", significant_digits);
while (n-- > 0) {
char buf[100];
form_text_number(buf, significant_digits, min_expo, max_expo);
if (!round_trip_text_double_text(buf, significant_digits)) {
return;
}
}
printf("None Failed\n");
}
int main(void) {
test_sig(10000, 16, -300, 300);
test_sig(10000, 16, -1, -1);
test_sig(1000000, 15, -300, 300);
test_sig(1000000, 15, -1, -1);
return 0;
}
Output
Sig digits 16: Round trip failed "8.995597974696435e+110" 8.995597974696434373e+110 "8.995597974696434e+110"
Sig digits 16: Round trip failed "6.654469376627144e-01" 6.654469376627144550e-01 "6.654469376627145e-01"
Sig digits 15: None Failed
Sig digits 15: None Failed
Note: When the double
was printed to 3 extra digits for many failed strings, those 3 digits were in the range 445 to 555.
float
or adouble
. You use of the word “guarantee” seems to indicate that you are interested in the number of correct digits when trying to represent a decimal number infloat
ordouble
. Technically, this number is zero, for instance both formats represent the decimal number0.999999999999999999999999995
as1.0
, getting no decimal digit correct. – Pascal Cuoq