Groups | Blog | Home
all groups > c# > november 2003 >

c# : float bug or bad implementation


Bret Mulvey
11/21/2003 2:06:25 PM

[quoted text, click to view]

Because the values are stored in binary. The value "4.6" is exact when
represented in base 10, but in base 2 it becomes an infinitely repeating
fraction "100.1001 1001 1001 ..." and therefore can only be approximated.

If you want to use base-10 for the internal representation, you can use the
"decimal" type which is C# equivalent to System.Decimal. This type uses base
10 for storing its exponent instead of base 2 used by other floating-point
types. "4.6" is stored as 46 x 10^-1 in the System.Decimal type.

David Browne
11/21/2003 5:45:55 PM

[quoted text, click to view]

floats, doubles and integers are finite subsets of the rational numbers.
floats are basically a subset of doubles, and doubles and integers are
mostly disjoint.

An integer can be "converted" to a float, but it's often just mapped to a
nearby float. The
A float and an integer are said to be equal if they are equal after the
integer is mapped to a float.

So

float f = 414/4.6f; // f == (float)90 since f is the float nearest to 90
double d1 = (double)(414/4.6d); //f == (double)90 since d1 is the double
nearest to 90
double d2 = (double)(414/4.6f); //f != (double)90

d2 != (double)90 because d2 was converted from a float (414.4/6f), and so it
is only as close to 90 as a float can get. A double can get a whole lot
closer.

Graphically it looks like this:


-
-90.000002 <----- the nearest float to 90 ( == f and d2)
-
-
-
-
-
-
-90.00000000000002 <---- the nearest double to 90 (d1)
-90
-


David

Kubik
11/21/2003 9:56:15 PM
Hi!

Let's see, we got:

float var=4.6f; //as we know 414/4.6 shoud be equal to 90

but Math.Ceiling(414/var) gives us 91

but (414/var).ToString() prints '90'.

And when we convert:
((double)(414/var)).ToString() we got '90,0000018658846'

I know how the floats are represented in memory and I know
limitations connected with, but why compiler and program
makes bugs in such simple cases??

Adam

Bruno Jouhier [MVP]
11/21/2003 10:30:31 PM
I'm not too surprised that Math.Ceiling(414/var) gives 91.

Floating point representation is such that there is no floating point number
that matches 4.6f, only numbers that approximate it. Then,
Math.Ceiling(414/var) may very well return 91. This is not a bug, just a
consequence of floating point representation and computation rules.

So, before classifying these odd behaviors as "bugs", I suggest that you
read the specs (IEEE FP specs, C# specs) and see if the results that you get
contradict the specs. I doubt that that the odd results that you experienced
are actually bugs.

If you want to get predictable rounding, you should use the decimal type.
Double will be a bit better than float, but still, you will get odd
behaviors, this is inherent to the FP representation.

Bruno.

"Kubik" <kubik@iname.com> a écrit dans le message de
news:O3NM6IHsDHA.3468@TK2MSFTNGP11.phx.gbl...
[quoted text, click to view]

Kubik
11/21/2003 10:50:38 PM

U¿ytkownik "Bruno Jouhier [MVP]" <bjouhier@club-internet.fr> napisa³ w
wiadomo¶ci news:efz7yaHsDHA.1764@TK2MSFTNGP10.phx.gbl...
[quoted text, click to view]
Yes, I agree, but it's very irritating. Especially when ToString(x+"="+y)
method
returns '50=50' string, but condition x==y isn't true. I was using for all
time
PHP interpreter, and there wasn't such problems with so simple values.
Moreover in C/C++ I also didn't experience such problems.

OK, finally I used decimal type. Thanks for your answer.

best regards
Adam

Eric Gunnerson [MS]
11/23/2003 8:29:00 PM
This article should help:

http://portal.acm.org/citation.cfm?id=103163&coll=portal&dl=ACM&CFID=14311829&CFTOKEN=43458177

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
[quoted text, click to view]

AddThis Social Bookmark Button