Created
November 2, 2015 20:06
-
-
Save encryptio/fe12b7ac8907ecb5369d to your computer and use it in GitHub Desktop.
Floating point weirdness
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile and run in 32-bit mode: | |
// $ cc -Wall -m32 -o test test.c | |
// $ ./test | |
// false | |
// | |
// Contrast with 64-bit mode: | |
// $ cc -Wall -m64 -o test test.c | |
// $ ./test | |
// true | |
// | |
// This happens because the default implementation of floating point math on | |
// 32-bit x86 is to use the 387 floating point instruction set, which has higher | |
// internal precision. Thus, "div" is flushed to RAM (and truncated to low | |
// precision), then the comparison loads it back into the 387 unit and does the | |
// division again (but does not truncate it before comparison, since it's not | |
// stored in a variable (memory.)) | |
// | |
// By contrast, 64-bit x86 uses the SSE instructions for floating point math, | |
// which has instructions for operations on 32-bit floats directly. Thus, its | |
// internal representation is already truncated to the proper size, and the | |
// equality check succeeds. | |
// | |
// You can compile and run in 32-bit mode with SSE (instead of 387): | |
// $ cc -Wall -m32 -mfpmath=sse -o test test.c | |
// $ ./test | |
// true | |
// | |
// You might need to set -msse or other options to get this to work; my "cc" is | |
// gcc 5.2.0. | |
#include <stdio.h> | |
int main(void) { | |
float three = 3.0f; | |
float seven = 7.0f; | |
float div = three/seven; | |
if (div == three/seven) | |
printf("true\n"); | |
else | |
printf("false\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment