Subtracting a float from a float not always working

I’ve been trying to solve this problem all evening. I’m either really stupid or doing something completely wrong.

I have 2 floats, Amount and Access defined as below:

float amount = UnityEngine.Random.Range(0f, 10000000f);
float access = (float)Math.Round(UnityEngine.Random.Range(0.1f, 1f), 1);

These are used to create a new mineral deposit class

 MineralDeposit mineralDeposit = new MineralDeposit(mineralType, amount, access);

MineralDeposit.cs

public class MineralDeposit
{
    public MineralDeposit(MineralType despositType, float amountInDesposit, float access)
    {
        DespositType = despositType;
        Amount = amountInDesposit;
        Access = access;
    }

    public float Access { get; private set; }

    public float Amount { get; private set; }

    public MineralType DespositType { get; private set; }

    public float RemoveFromDeposit(float amountToRemove)
    {
        if (amountToRemove > Amount)
        {
            Amount = 0;
            return amountToRemove;
        }
        else
        {
            UnityEngine.Debug.Log(Amount);
            Amount -= amountToRemove;
            return amountToRemove;
        }
    }
}

The RemoveFromDeposit method is called like this:

float amountMined = minerals.RemoveFromDeposit(minerals.Access / 10f);

The method is returning correct but the issue is the Amount variable in the MineralDeposit class isn’t subtracting. It works if I use RemoveFromDeposit(minerals.Access * 10f); but whenever it gets a smallish float passed it’s refusing to subtract.

I’m am doing something blatantly wrong here?

Thanks.

That’s because you just run out of significant digits. I’ve posted a reference table over here. The larger the value of a float gets, the larger the smallest possible difference gets.

If your value is around 10 million you are in the range “8M - 16M”. The smallest representable difference is “1.0” in this case. Anything smaller than that can not have any effect on the number. It’s a floating point number. The precision varies depending on how large the number is.

edit

If you really need to work with that large values and that small values at the same time you may want to split the number into two variables. One long values to store the whole number part and a float to store just the fraction. Of course the first step could be to simply switch to double instead of float. Though if the numbers might get much larger you may run into problems with doubles as well.

When using a long / float combination you would add / subtract an amount from the float part first and then carry the whole number part from the float to the long variable.

Example

f = 0.5f;
l = 10000000;
// add 2.0123
f += 2.0123f; // --> 2.5123

int a = Mathf.FloorToInt(f); // --> 2
f -= a; // --> 0.5123
l += a; // --> 10000002

// subtract 5.7f
f -= 5.5f; // --> -4.9877

int a = Mathf.FloorToInt(f); // --> -5
f -= a; // --> 0.0123
l += a; // --> 9999997

I might be wrong, but i think your get/set’s are not doing anything.

At least you should update and/or return a local variable, and use this instead of accessing the variable directly.

float _access;
val { get { return _access; } set { _access = value; } }