Determine if the operation will overflow?
I have several classes in my application that represent physical units like temperature. These classes have the ability to have some units associated with them and modified, such as Celcius and Kelvin. They also have custom Max and Min values.
When I want to change units, I get a conversion factor between the two given units, and then change the values Min
, Max
and Data
in the class, doing some arithmetic operation with the conversion factor.
Double ConversionFactor = GetConversionFactor(curUnits, newUnits);
Units = newUnits;
Min *= ConversionFactor;
Max *= ConversionFactor;
Data *= ConversionFactor;
The problem is that sometimes the user can accept max and min values MinValue
and MaxValue
some type for example Double
. If the user had to change units that have a conversion factor greater than 1, it will overflow.
Is there a way in C # to determine if this overflow and overflow will happen?
From what I can tell with some tests, I think I just need to check that the result of an operation is not positive or negative infinity? If so, I can just set the value back to MinValue
or MaxValue
.
Also, a bonus question. In my testing I found that if I create Double max = Double.MaxValue
and add something small like 100 to it. The value doesn't change.
Why is this? Is there some kind of threshold between MaxValue
and PositiveInfinity
, because the accuracy is so small at this large value?
If the variable is double you should check Infinity
.
The best way to do this is to use double.IsInfinity
that will check for both underflow and overflow (positive and negative infinity).
bool overflowed = double.IsInfinity(Min);
You can wrap this in your own extension method or so if you like.
If the variable is an integer, you can wrap it in a block checked
, which will throw an exception when the operation overflows. It is not proactive, but it does the job.
checked
{
...
}
You can try...catch
do it.
Floating point arithmetic does not throw an exception.
Instead, you should perform the operation and then check the results, for example:
double d1 = double.MaxValue;
double d2 = double.MaxValue;
double d3 = d1*d2;
if (double.IsInfinity(d3))
Console.WriteLine("Infinity");
if (double.IsPositiveInfinity(d3))
Console.WriteLine("Positive Infinity");
d1 = double.MinValue;
d2 = double.MaxValue;
d3 = d1*d2;
if (double.IsInfinity(d3))
Console.WriteLine("Infinity");
if (double.IsNegativeInfinity(d3))
Console.WriteLine("Negative Infinity");
Note what double.IsInfinity(d)
will be true if true double.IsPositiveInfinity(d)
or double.IsNegativeInfinity()
.
As you noticed, adding a relatively small number to double.MaxValue
does not result in double.Infinity
. This is due to rounding - the value you add is less than the value that can be represented for a double with such a large exponent.