/* * From: David Goldberg * To: numeric-interest@validgh.com * Subject: Re: 7 digit decimal number * Message-Id: <99Apr12.091046pdt.177505@arcturia.parc.xerox.com> * Date: Mon, 12 Apr 1999 09:10:41 PDT * Sender: owner-numeric-interest@validgh.com * Precedence: bulk * Reply-To: David Goldberg * * Jerome beat me to the punch. My answer was slightly smaller, * 9.0e9. Here is the program with comments that prints out * a lot of examples (include 9.0e9): * * -david * */ /* * Find 7 digit decimal number d so that d rounded to 24 bits * (single prec) and back to 7 digits does not recover d. * * Use fact that 2^33 = 8589934592 * and 10^10 = 10000000000 * * are close, so that there are more decimal numbers * with 7 digits in the range (2^33, 10^10) than binary numbers * with 24 bits. Computing how many numbers in that range: * * 7 digit decimal numbers in (2^33, 10^10) are of form * i*10^3, 2^33/10^3 < i < 10^7 * 24 bit binary numbers in (2^33, 10^10) are of form * j*2^10, 2^23 < j < 10^10/2^10 * * 10^7 - 2^33/10^3 = 1410065 decimal numbers * 10^10/2^10 - 2^23 = 1377017 binary numbers * * Other pairs besides (2^33, 10^10) are (2^43, 10^13), * (2^53,10^16), (2^63,10^19), etc. * */ #include #include #include #include #include "args.h" #if STDC double anint(double x) /* missing function: added by NHFB */ #else double anint(x) /* missing function: added by NHFB */ double x; #endif { if (x != x) return (double)INT_MIN; else if ((x - 0.5) < (double)INT_MIN) return (double)INT_MIN; else if ((x + 0.5) > (double)INT_MAX) return (double)INT_MAX; else if (x < 0.0) return (double)(long)(x - 0.5); else return (double)(long)(x + 0.5); } int main(VOID_ARG) { double dlow, dhi, i, x, m; double d; /* the 7 decimal number */ double b; /* rounded to 24 bit binary */ dlow = ceil(scalb(1.0, 33.0)/1000.0); /* 2^33/10^3 */ dhi = 10000000.0; /* 10^7 */ m = 536870913.0; /* 2^k + 1 = 2^29 + 1 */ for (i = dlow; i < dhi; i++) { d = i*1000.0; /* round to 24 bits, k=29 p-k=24 */ b = x = (m*d) - (m*d - d); /* round back to 7 decimal digits */ x = anint(x/1000.0)*1000.0; if (x != d) { (void)printf("%9.0f, %.0f x 2^10, %9.0f\n", d, b/1024.0, x); } } return (EXIT_SUCCESS); } /* * First answer is 8589973000, 8388646 x 2^10, 8589974000 * * Checking: * 8589973000 is 100000000000000000100101 1000001000 * which rounds to 100000000000000000100110 0000000000 * which in decimal is 8589973 504 * which rounds to 8589974 000 */