This is what happens on my computer:
(double)(float)0.6
= 0.60000002384185791
(double)0.6f
= 0.60000002384185791
(double)(6/10f)
= 0.6
(double)(float)(6/10f)
= 0.6
6/10f is also a float,how come it can be precisely 0.6?
In my mind (double)(6/10f) should also be 0.60000002384185791.
Can someone help explain this? thanks!
The constant 0.5 declares a double in Objective-C, putting an f on the end - 0.5f declares the constant as a (32-bit) float.
The values used in an expression are considered as double (double precision floating point format) unless a 'f' is specified at the end. So the expression “x==0.1” has a double on right side and float which are stored in a single precision floating point format on left side.
Description. It is very usual for the C programming language beginners to compare a floating point number using the "==" operator. Floating point numbers must not be compared with the "==" operator.
Float is a shortened term for "floating point." By definition, it's a fundamental data type built into the compiler that's used to define numeric values with floating decimal points. C, C++, C# and many other programming languages recognize float as a data type. Other common data types include int and double.
First, its important to bear in mind that 0.6
cannot be accurately represented as a float
however it can be accurately represented as a double
(the inaccuracies of floating point arithmetic are well documented, if its not clear why 0.6
cannot be accurately represented as a float, try this link)
The reason why you are seeing the above behaviour is down to the compiler - if you take a look at the compiled assembly in reflector then whats going on here is a little clearer:
(UPDATE I've changed the code so that it doesn't use Console.WriteLine
, as I realised that the compiler was choosing an overload for you, which confused the situation)
// As written in source
var j = (double)(float)0.6;
var k = (double)0.6f;
var l = (double)(6/10f);
var m = (double)(float)(6/10f);
// Code as seen by Reflector
double j = 0.60000002384185791;
double k = 0.60000002384185791;
double l = 0.6;
double m = 0.6;
Why the compiler chooses to compile in this particular way is beyond me (fyi, this is all with optimisations turned off)
Some interesting other cases:
// Code
var a = 0.6;
var b = (double)0.6;
var c = 0.6f;
var d = (float)0.6;
var e = 6 / 10;
var f = 6 / (10f);
var g = (float)(6 / 10);
var h = 6 / 10f;
var i = (double)6 / 10;
// Prints out 0.60000002384185791
double n = (float)0.6;
double o = f;
// As seen by Reflector
double a = 0.6;
double b = 0.6;
float c = 0.6f;
float d = 0.6f;
int e = 0;
float f = 0.6f;
float g = 0f;
float h = 0.6f;
double i = 0.6;
double n = 0.60000002384185791;
double o = f;
The compiler only seems to do the above trick in a couple of special cases, why it does this only when casting to a double is completely beyond me!
The rest of the time it seems to do some trickery to make floating point arithmetic seem to work where in fact it normally wouldn't.
It appears to be rounding the result. Are you displaying the result with the necessary digits of precision? You can use this c# class from Jon Skeet to get the exact numeric representation of the result printed out.
Note that ToString()
will not always print all of the digits, nor will the Visual Studio debugger.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With