Search code examples
c#floating-pointoverflow

Determine if operation will result in overflow?


I have some classes within my application that represent physical units, for instance temperature. These classes have the ability to have some units associated with them and changed, such as Celcius and Kelvin. They also have user defined Max and Min values.

When I want to change units I get a conversion factor between the two given units and then alter the Min, Max, and Data values within the class by performing some arithmetic operation with the conversion factor.

Double ConversionFactor = GetConversionFactor(curUnits, newUnits);
Units = newUnits;
Min *= ConversionFactor;
Max *= ConversionFactor;
Data *= ConversionFactor;

The issue I am having is that sometimes a user might allow the max and min values to be the MinValue and MaxValue of some type such as Double. If a user were to change units that have a conversion factor larger than 1 this will result in overflow.

Is there a way in C# to detect if this overflow will happen for both overflow and underflow?

From what I can tell with some tests I think I just need to check that the result of the operation does not equal positive or negative infinity? If so I can then just set the value back to either MinValue or MaxValue.

Also, bonus question. In my testing I found that if I create a Double max = Double.MaxValue and add something small like 100 to it. The value does not change.

Why is this? Is there some threshold between MaxValue and PositiveInfinity because the precision is so low at that large of value?


Solution

  • If the variable is a double, you should check for Infinity.

    The best way to do that is by using double.IsInfinity, which will check for both underflow and overflow (positive and negative infinity).

    bool overflowed = double.IsInfinity(Min);
    

    You can wrap that in an own extension method or so if you want to.


    If the variable is an integer you can wrap the statement in a checked block, which will cause an exception when the operation overflows. This isn't preventive, but it does the job.

    checked
    {
       ...
    }
    

    You can try...catch that.