Ferit Buyukkececi
Ferit Buyukkececi

Reputation: 2685

Floating-point error when not assigned to a float variable

I have the static method GetFraction which returns the cents in a price as below:

public static class PriceUtil
{
    public static int GetFraction(float price)
    {
        int PriceInt = (int)(100 * price);

        return PriceInt % 100;
    }
}

For the price $23.79, this method returns 78 Cents instead of 79. While debugging, I fixed the bug unintentionally as follows:

public static class PriceUtil
{
    public static int GetFraction(float price)
    {
        float PriceFloat = 100 * price;
        int PriceInt = (int)(PriceFloat);

        return PriceInt % 100;
    }
}

I don't understand why assigning the (100 * price) to a float variable solves the problem. AFAIK, casting to integer is applied to exactly same value as int times float is float anyways.

Thanks in advance for your replies!

Upvotes: 0

Views: 257

Answers (1)

Martin Liversage
Martin Liversage

Reputation: 106826

As it has been noted in the comments you should be using decimal as the type instead of float to avoid this kind of problem.

Using the value 23.79f does not exhibit the problem you describe on my computer so my guess is that the price has been computed by some previous calculation. Here is a demonstration:

var value = 23.7899999f;
Console.WriteLine(value);
var fraction = ((int) (value*100))%100;
Console.WriteLine(fraction);

The output of this code is

23.79
78

Another possibility of the problem you experience is that float is a 32 bit floating point number and internally on the CPU calculations are often performed using 80 bit floating point numbers. If you change the way you perform your calculations you may see slightly different results depending on when the rounding or truncation is performed. However, I doubt that this is the explanation of the results that you experience.

You should be able to solve your problem by rounding the value before computing the fraction:

var value = 23.7899999f;
Console.WriteLine(value);
var roundedValue = Math.Round(value, 2);
var fraction = ((int) 100*roundedValue)%100;
Console.WriteLine(fraction);

The output is now

23.79
79

Upvotes: 1

Related Questions