Reputation: 898
So I have the following code:
#include <iostream>
int main(){
float number = 0.6;
int anotherNumber = 20;
int value = (int) ((float) anotherNumber * number);
std::cout << value;
std::cin.get();
}
It gives 12, like it should considering 20 * 0.6 = 12. However, if I change all floats to doubles:
#include <iostream>
int main(){
double number = 0.6;
int anotherNumber = 20;
int value = (int) ((double) anotherNumber * number);
std::cout << value;
std::cin.get();
}
It gives me 11 instead. And to make things even weirder, if I change the code so that the value is stored in a variable first and then case after, it gives the right answer (12) again.
#include <iostream>
int main(){
double number = 0.6;
int anotherNumber = 20;
double intermediate = (double) anotherNumber * number;
int value = (int) intermediate;
std::cout << value;
std::cin.get();
}
What in God's name is going on here? I'm using g++ 4.5.3 to compile.
Upvotes: 1
Views: 5099
Reputation: 72539
0.6
cannot be represented in any binary floating point format exactly. Sometimes it somewhat larger and somewhat it's somewhat smaller, depending on the data-type. See What Every Programmer Should Know About Floating-Point Arithmetic for detailed explanation.
The 'store in memory' version is different because the x87 FPU uses 80-bit floating point registers internally.
EDIT: Detailed computation:
float 0.6 in memory;
.100110011001100110011010
loaded to register:
.10011001100110011001101000000000000000000000000000000000000000000
multiplied by 20:
1100.0000000000000000000010000000000000000000000000000000000000000
rounded down:
1100
double 0.6 in memory
.10011001100110011001100110011001100110011001100110011
loaded to register:
.10011001100110011001100110011001100110011001100110011000000000000
multiplied by 20:
1011.1111111111111111111111111111111111111111111111111110000000000
rounded down:
1011
double 0.6 in memory
.10011001100110011001100110011001100110011001100110011
loaded to register:
.10011001100110011001100110011001100110011001100110011000000000000
multiplied by 20:
1011.1111111111111111111111111111111111111111111111111110000000000
converted to double-precision and stored to memory:
1100.0000000000000000000000000000000000000000000000000
loaded to register:
1100.0000000000000000000000000000000000000000000000000000000000000
rounded down:
1100
Upvotes: 8