Standing on the Beach, Staring at the C
Total Page:16
File Type:pdf, Size:1020Kb
Lowering the Level of Conversation @KevlinHenney https://twitter.com/KevlinHenney/status/761081424493449217 A goto completely invalidates the high-level structure of the code. Taligent's Guide to Designing Programs / WordFriday snowclone, noun ▪ clichéd wording used as a template, typically originating in a single quote ▪ e.g., "X considered harmful", "These aren't the Xs you're looking for", "X is the new Y", "It's X, but not as we know it", "No X left behind", "It's Xs all the way down", "All your X are belong to us" send(to, from, count) register short *to, *from; register count; { register n=(count+7)/8; switch(count%8){ case 0: do{ *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; }while(--n>0); } } send(to, from, count) register short *to, *from; register count; I feel {a combination of register n=(count+7)/8; switch(count%8){ case 0: do{ *to = *from++; pride andcase 7: revulsion *to = *from++; at case 6: *to = *from++; case 5: *to = *from++; this discovery.case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; }while(--n>0); } Tom Duff } send(to, from, count) register short *to, *from; Many peopleregister have count; said that the worst { feature of Cregister is that n=(count+7)/8; switches don't break switch(count%8){ automaticallycase before 0: do{ *to each = *from++; case label. case 7: *to = *from++; This code formscase 6: some *to sort = *from++; of argument case 5: *to = *from++; in that debate,case but4: I'm *to not = *from++; sure whether it's for or against.case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; }while(--n>0); } Tom Duff } Earliest informal standard set by 1st edition of The C Programming Language First de jure standard, included properly typed function declarations (function prototypes), const, better i18n support First international standard — basically C89 rebadged Significant update with new language and library features, including better IEEE 754 support, compound literals and portable data types Support for threading, type-generic expressions and safer bounds-checking library functions 16-bit void * short int long 32-bit void * short int long 32-bit void * short int long long long 64-bit void * short int long long long LP64 void * short int long long long Java & C# short int long LLP64 void * short int long long long int8_t int_least8_t int_fast8_t uint8_t uint_least8_t uint_fast8_t int16_t int_least16_t int_fast16_t uint16_t uint_least16_t uint_fast16_t int32_t int_least32_t int_fast32_t uint32_t uint_least32_t uint_fast32_t int64_t int_least64_t int_fast64_t uint64_t uint_least64_t uint_fast64_t intptr_t uintptr_t Signed magnitude A sign bit, 0 for + and 1 for –, is followed by the bits representing the integer's magnitude 640210 00011001000000102 -640210 10011001000000102 0 00000000000000002 -0 10000000000000002 One's complement Negative integers are represented as the bitwise complement of the corresponding positive integer, i.e., –i is equivalent to ~i 640210 00011001000000102 -640210 11100110111111012 0 00000000000000002 -0 11111111111111112 Two's complement Negative integers are represented 1 plus as the bitwise complement of the corresponding positive integer, i.e., –i is equivalent to ~i + 1, which is the same as saying that it is the complement with respect to 2N 640210 00011001000000102 -640210 11100110111111102 0 00000000000000002 28 256 27-1 127 -27 -128 216 65536 215-1 32767 -215 -32768 232 4294967296 231-1 2147483647 -231 -2147483648 264 18446744073709551616 263-1 9223372036854775807 -263 -9223372036854775808 32767 __________+ 1 __________32768 32767 __________+ 1 undefined__________ 32767 __________+ 1 __________-32768 INT_MIN __________- INT_MIN __________0 INT_MIN __________+ INT_MIN __________0 Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken Joshua Bloch https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html I was shocked to learn that the binary search program that Bentley proved correct and subsequently tested in Chapter 5 of Programming Pearls contains a bug. https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html Lest you think I'm picking on Bentley, let me tell you how I discovered the bug: The version of binary search that I wrote for the JDK contained the same bug. https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html https://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html (low + high) / 2 low / 2 + high / 2 low + (high – low) / 2 time_t int main(void) { const time_t end_of_time = INT_MAX; puts(asctime(gmtime(&end_of_time))); return 0; } Tue Jan 19 03:14:07 2038 int main(void) { const time_t end_of_time = INT_MAX + 1; puts(asctime(gmtime(&end_of_time))); return 0; } Fri Dec 13 20:45:52 1901 printf("%f", 0.1 + 0.2); 0.300000 assert(0.1 + 0.2 == 0.3); assert(0.1 + 0.2 == 0.3); printf("%.17f", 0.1 + 0.2); 0.30000000000000004 Floating-Point Numbers Aren't Real Chuck Allison Real numbers have infinite precision and are therefore continuous and nonlossy; floating-point numbers have limited precision, so they are finite, and they resemble "badly behaved" integers, because they’re not evenly spaced throughout their range. Chuck Allison It should go without saying that you shouldn't use floating-point numbers for financial applications — that's what decimal classes in languages like Python and C# are for. Chuck Allison significand bias exponent single precision 32-bit double precision 64-bit extended precision 64-,80- or 128-bit single precision 32-bit IEEE 754 sign biased exponent significand double same_birthday(int people); // Return the probability that at least 2 people out of a sample // of size 'people' share the same birthday, assuming a uniform // distribution of birthdays and ignoring leap days. int main(void) { int people = 0; while (same_birthday(people) < 0.5) ++people; printf("%i", people); return 0; } double same_birthday(int people) { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 – probability) * i / 365.0; return probability; } int main(void) { int people = 0; while (same_birthday(people) < 0.5) ++people; printf("%i", people); return 0; } http://xkcd.com/552/ Correlation doesn't imply causation, but it does waggle its eyebrows suggestively and gesture furtively while mouthing 'look over there'. double same_birthday(int people) { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 - probability) * i / 365.0; return probability; } double same_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 - probability) * i / 365.0; return probability; } } double same_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else if (people > 365) { return 1; } else { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 - probability) * i / 365.0; return probability; } } assert(same_birthday(0) == 0); assert(same_birthday(1) == 0); assert(same_birthday(2) > 0); ... assert(same_birthday(365) < 1); assert(same_birthday(366) == 1); assert(same_birthday(367) == 1); ... assert(same_birthday(INT_MAX) == 1); assert(same_birthday(0) == 0); assert(same_birthday(1) == 0); assert(same_birthday(2) > 0); ... assert(same_birthday(365) < 1); assert(same_birthday(366) == 1); assert(same_birthday(367) == 1); ... assert(same_birthday(INT_MAX) == 1); assert(same_birthday(0) == 0); assert(same_birthday(1) == 0); assert(same_birthday(2) > 0); ... assert(same_birthday(183) < 1); assert(same_birthday(184) < 1); ... assert(same_birthday(365) < 1); assert(same_birthday(366) == 1); assert(same_birthday(367) == 1); ... assert(same_birthday(INT_MAX) == 1); The real value of tests is not that they detect bugs in the code but that they detect inadequacies in the methods, concentration, and skills of those who design and produce the code. C A R Hoare double unique_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else if (people > 365) { return 0; } else { double probability = 1; const int nonpeople = 366 – people; for (int i = 364; i >= nonpeople; --i) probability *= i / 365.0; return probability; } } double same_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else if (people > 365) { return 1; } else { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 - probability) * i / 365.0; if (probability == 1) --*(uint64_t *) &probability; return probability; } } assert(same_birthday(0) == 0); assert(same_birthday(1) == 0); assert(same_birthday(2) > 0); ... assert(same_birthday(183) < 1); assert(same_birthday(184) < 1); ... assert(same_birthday(365) < 1); assert(same_birthday(366) == 1); assert(same_birthday(367) == 1); ... assert(same_birthday(INT_MAX) == 1); printf("%.15f", same_birthday(365)); 1.000000000000000 printf("%.16f", same_birthday(365)); 0.9999999999999999 double same_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else if (people > 365) { return 1; } else { double probability = 0; for (int i = 1; i < people; ++i) probability += (1 - probability) * i / 365.0; if (probability == 1) --*(uint64_t *) &probability; return probability; } } double same_birthday(int people) { if (people < 0) { errno = EDOM; return NAN; } else if (people > 365) { return 1; } else { double probability = 0; for (int i = 1; i < people; ++i) probability +=