Вопрос: Определите, приведет ли операция к переполнению?


У меня есть несколько классов в моем приложении, которые представляют физические единицы, например, температуру. Эти классы имеют возможность иметь некоторые единицы, связанные с ними и измененные, такие как Celcius и Kelvin. Они также имеют пользовательские значения Max и Min.

Когда я хочу изменить единицы, я получаю коэффициент преобразования между двумя данными единицами, а затем изменяю Min, Max, а также Data значения внутри класса, выполнив некоторую арифметическую операцию с коэффициентом пересчета.

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

Проблема, с которой я сталкиваюсь, заключается в том, что иногда пользователь может позволить значениям max и min быть MinValue а также MaxValue какого-либо типа, такого как Double, Если пользователь должен был изменить единицы, у которых коэффициент преобразования больше 1, это приведет к переполнению.

Есть ли способ в C # определить, произойдет ли это переполнение как для переполнения, так и для нижнего потока?

Из того, что я могу сказать с некоторыми тестами, я думаю, мне просто нужно проверить, что результат операции не равен положительной или отрицательной бесконечности? Если это так, я могу просто вернуть значение обратно MinValue или же MaxValue,

Также, бонусный вопрос. В ходе тестирования я обнаружил, что если я создаю Double max = Double.MaxValue и добавить что-то маленькое, как 100 к нему. Значение не изменяется.

Почему это?  Существует ли некоторый порог между MaxValue а также PositiveInfinity потому что точность настолько низкая при такой большой стоимости?


3


источник


Ответы:


Если переменная является двойной, вы должны проверить Infinity,

Лучший способ сделать это - использовать double.IsInfinity, который будет проверять как нижнее, так и переполнение (положительная и отрицательная бесконечность).

bool overflowed = double.IsInfinity(Min);

Вы можете обернуть это в свой собственный метод расширения или, если хотите.


Если переменная является целым числом, вы можете обернуть ее в checked блок, который вызовет исключение при переполнении операции. Это не превентивно, но он выполняет эту работу.

checked
{
   ...
}

Вы можете try...catch тот.


5



Арифметика с плавающей точкой не вызывает исключений.

Вместо этого вы должны выполнить операцию, а затем проверить результаты, например:

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");

Обратите внимание, что double.IsInfinity(d) будет истинным, если double.IsPositiveInfinity(d) или же double.IsNegativeInfinity() правда.

Как вы заметили, добавив относительно небольшое число double.MaxValue не приводит к double.Infinity, Это из-за округления - значение, которое вы добавляете, меньше, чем значение, которое может быть представлено для double с таким большим экспонентом.


1