简体   繁体   中英

Do floating point numbers lose precision if no operations are done on them

I have a class like such:

public class Test
{
    public void CheckValue(float val)
    {
        if (val == 0f)
        {
            //Do something
        }
    }
}

//Somewhere else..
void SomeMethod
{
    Test t = new Test();
    t.CheckValue(0f);
}

Is it guaranteed that checking if (val == 0f) will return true ? Or will floating point numbers only lose precision when you perform operations with them?

They don't lose precision. There are inaccuracies in describing some floating point values in decimal. When doing operations on them, those inaccuracies can add up or cancel each other out.

In your case, 0 can be described completely accurately both in decimal and as a binary floating point, so it should work. Other values might not be and you should (as others point out) not rely on == for floating point values.

See more information here: http://floating-point-gui.de/

What it comes down to is that you can't perfectly represent every floating point number (in all their infinite variance) in the 32 bits worth of memory that holds a float . A number that can't be represented perfectly will only have a very small error value, but it will be there.

For example, 1/3 is (roughly) 0.333333343267 in the nearest float representation. You've got 7 decimal digits of accuracy, then it hits a bit of a snag. So let's say you divide 1 by 3, then later multiply by 3. The result isn't 1, it's 1.0000000298 and change. So (1/3)*3 =/= 1 .

These representational errors are why directly comparing floating point values is considered poor practice.

In situations where you need to minimize the impact of these little errors you should do whatever you can to stop them from accumulating. Rotating a set of coordinates a little at a time for instance will give you imperfect results, since the errors introduced by each rotation operation (using sin and cos values that are unlikely to have perfect float representations) will accumulate over time. Better to track the total angular change and rotate the original vector each time to get smaller error values.

Another place this can bite you is in a for loop. If you want to do 10,000 steps at 1/30000 per step, use an int for the loop variable and calculate the current position as a division. Slower, yes, but far more accurate. Using floats your error accumulates until you have only about 3 reliable decimal digits of significance, instead of over 7 if you divide each time.

Speed is nice, but precision is nicer in some circumstances.

And yes, it seems silly, but these errors can really mount up. Not so important in some places, rampant error factories in others.

You should never compare floating-point-numbers with "==". Instead you can use a border. For example instead of comparing == 0 you can do something like

float border = 0.00000001;
if( (val - border) <= 0 && (val + border) >= 0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM