Ограничение переполнения значения C #

#c# #overflow

#c# #переполнение

Вопрос:

Мне нужно ограничить значение при переполнении. Я реализовал это следующим образом:

     public static sbyte LimitValueToSByte(this int val)
    {
        if (val > sbyte.MaxValue) return sbyte.MaxValue;
        if (val < sbyte.MinValue) return sbyte.MinValue;
        return (sbyte)val;
    }
  

Есть ли более элегантный способ?

Это код в системе, критичной по времени, поэтому важна производительность.

Ответ №1:

Это похоже на идеально читаемый и корректный код, который не нуждается в каком-либо улучшении вообще. Это просто название метода. Может быть, использовать ToSbyte вместо LimitValueToSByte .

Ответ №2:

Не могу придумать лучшего способа написать эту функцию.

Я бы назвал это ClampToSByte , поскольку обычно вызывается такая операция ограничения Clamp . Limit немного менее специфично и допускает другие граничные условия, такие как обтекание.

Вы должны быть осторожны, если вы реализуете аналогичный код для чисел с плавающей запятой. В частности, вам нужно решить, какое поведение вы хотите для NaN s и подписанных нулей. Но, к счастью, с целыми значениями проблем нет.

Комментарии:

1. Нули со знаком не должны быть проблемой.

2. @Slaks не с целыми числами. Но (-0.0).Clamp(0,1) возвращает -0 то, что может быть нежелательно во всех ситуациях.

3. Я знаю о подписанных нулях, но здесь они не вызовут проблем. В .Net -0.0 неотличимо от 0.0 .

4. 1/(-0.0) отличается от 1/( 0.0) . Таким образом, они могут приводить к разным результатам, когда они используются в вычислениях.

5. Я беру свои слова обратно. Однако здесь это не вызовет проблем, поскольку он просто выполняет сравнения, а целочисленные типы не имеют подписанных нулей.

Ответ №3:

Для меня выглядит довольно неплохо. Если вы хотите что-то более элегантное, как насчет общей функции clamp?

 public static T Clamp<T>(this T value, T min, T max)
    where T : IComparable<T>
{
    if (value.CompareTo(min) <= 0) return min;
    if (value.CompareTo(max) >= 0) return max;
    return value;
}
  

(Предупреждение: я не тестировал это.) Вы могли бы использовать это так:

 int a = 42;
sbyte b = (sbyte)a.Clamp(sbyte.MinValue, sbyte.MaxValue);
  

Комментарии:

1. Я бы использовал IComparable<T> , чтобы избежать боксирования для типов значений.

2. @CodeInChaos: Я понятия не имел, что это предотвратит блокировку. Спасибо.

Ответ №4:

Мое новое решение этой проблемы:

 public static sbyte Clamp(this int val)
{
    return (sbyte)Math.Max(Math.Min(value, sbyte.MaxValue), sbyte.MinValue);
}