Page view counter

Silverlight Tips of the Day - Blog by Mike Snow

Game Programming with Silverlight

Silverlight Tip of the Day #40: 1.05 != 1.05 - Peril with Floating Point Comparisons.

The other day I found a bug in one of my Silverlight applications that was doing floating point comparisons.

In my animation of an image I was increasing the ScaleTransform.ScaleX by “0.05” from “0.0” to “2.0 and checking to see when my ScaleTransform.ScaleX= “2.0”. The problem was it was never reaching exactly 2.0.  Talking with my co-workers it turns out this is a side effect of parsing a float, the divide by 10 isn’t precise with a base 2 float representation. For example, looking in the debugger, when I set ScaleX = 1.05 the actual value turned out to be 1.0499999523162842.

Moral of the story: “Comparing floating point is fraught with peril. Do not rely on comparisons with floats or exact fuzzy with epsilon. That is, floating computation has errors so never do equal comparisons. Also, you should generally never introduce an epsilon and do a fuzzy comparison since it simply pushes your bugs to some other range of numbers you likely don’t test.”

Below is the wrong way to do it. This is an infinite loop since it never reaches exactly 2.0. In my debugger, it hit 1.9999991655349731 and then 2.0499992370605469.

scale.ScaleX = 0.0;
while (scale.ScaleX != 2.0)
{
    scale.ScaleX += 0.05;
    // Do stuff here...
}


Alternate way (compare to less than equal)

scale.ScaleX = 0.0;
while (scale.ScaleX < 2.0)
{
    scale.ScaleX += 0.05;
    // Do stuff here...
}

 

Thank you,
--Mike Snow

 Subscribe in a reader

Comments

Blogs said:

The other day I found a bug in one of my Silverlight applications that was doing floating point comparisons

# September 12, 2008 1:17 PM

Skyrunner said:

It's like in any other application.

Floating calcul has always been bad.

float f1 = 0.1f * 0.1f;

float f2 = 0.01f;

if (f1.Equals(f2)) Console.WriteLine("f1 = f2");

Should use float.Epsilon for compare them.

# September 12, 2008 4:17 PM

zgor said:

I don't feel comfortable with your alternative solution. It is of course an alternative but I don't want to multiply 0.05 by 40 in mind to get 2.0, my actual loop ending number.

My way would be the following:

scale.ScaleX = 0.0;

while (scale.ScaleX <= 2.0)

{

   scale.ScaleX += 0.05;

   // Do stuff here...

}

[ you see, we don't have a "40" in the code :) ]

# September 13, 2008 8:18 AM

Dew Drop - September 13, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - September 13, 2008 | Alvin Ashcraft's Morning Dew

# September 13, 2008 9:53 AM

mike.snow said:

ZGor - Actually I agree, i'll change it to your solution.

# September 13, 2008 12:20 PM

michaeldrotar said:

Good tip. Floating point comparisons are often a source of frustration.

The examples aren't quite equivalent though. The first one is saying to stop when scaleX is 2.0 and the second is saying to stop when scaleX is greater than 2.0

# September 13, 2008 10:39 PM

Community Blogs said:

Martin Mihaylov on the DataGrid, Bart Czernicki on Game Concepts, James Bacon on an update to Mashooo

# September 15, 2008 3:20 PM

Visual Web Developer Team Blog said:

Silverlight Tip of the Day #46 Title: Font Support in Silverlight Silverlight Tip of the Day #45: Title:

# September 25, 2008 1:56 PM

Silverlight Tips of the Day - Blog by Mike Snow said:

The purpose of this post is to create an outline summary all the blogs from my Silverlight tips of the

# January 2, 2009 5:57 PM

Silverlight Tips of the Day - Blog by Mike Snow said:

The purpose of this post is to create an outline summary all the blogs from my Silverlight tips of the

# January 2, 2009 5:57 PM

o UAU nosso de cada dia said:

essa lista eu copiei desse blog bárbaro (acompanhe por RSS você também): uma lista de dicas super úteis

# January 3, 2009 6:25 AM