Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is (double)0.6f > (double)(6/10f)?

Tags:

c#

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!

like image 908
zhy2002 Avatar asked Sep 20 '10 04:09

zhy2002


People also ask

What is 0.5 F in C++?

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.

What does 0.1 F mean in C?

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.

Can we compare two float values in C?

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.

What is a float in C?

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.


2 Answers

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.

like image 97
Justin Avatar answered Nov 15 '22 18:11

Justin


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.

like image 33
Robert Harvey Avatar answered Nov 15 '22 17:11

Robert Harvey