#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);
}