#rust #unsigned #signed
#Ржавчина #без знака #подписано
Вопрос:
Я хочу добавить an isize
в a usize
и включить проверку границ, чтобы результат не выходил за пределы a usize
. Как это можно сделать?
Ответ №1:
Вы могли бы использовать комбинацию isize::is_negative()
, isize::wrapping_abs()
, usize::checked_add()
и usize::checked_sub()
.
const fn add(lhs: usize, rhs: isize) -> Option<usize> {
if rhs.is_negative() {
lhs.checked_sub(rhs.wrapping_abs() as usize)
} else {
lhs.checked_add(rhs as usize)
}
}
Почему isize::is_negative()
vs rhs < 0
? В данном случае это ничего не меняет, так как логические операции с литералами считаются постоянными выражениями.
Однако, хотя это разрешено для литералов, это вообще запрещено, поскольку методы признаков не могут быть const
. Так что, если бы у вас был тип обертывания, например Foo(isize)
, тогда было бы запрещено говорить foo < Foo(0)
в контексте const. Хотя можно было бы сказать foo.is_negative()
, что as Foo
все еще может реализовать a const fn is_negative()
.
Да, вы все еще могли бы сказать foo.0 < 0
, но это не то, что я пытался сказать.
Комментарии:
1. джей Си, есть ли причина предпочесть
is_negative()
< 0
это?2. Не будет ли это переполняться, если
rhs
естьisize::MIN
?3. Использование
x < 0
тоже хорошо, и да, оно переполняется, я обновил ответ для использованияwrapping_abs()
.4. @kmdreko Я добавил некоторый контекст к почему
is_negative()
vs< 0
5. @goose121 No. isize::MIN равно 0b1000..000 и
-(isize::MIN 1)
равно 0b0111..1111 итакisize::MIN as usize == (isize::MIN 1) as usize 1
.
Ответ №2:
Одним из способов сделать это было бы использовать функцию, подобную следующей:
fn signed_unsigned_add(x: usize, y: isize) -> usize {
let (n, overflow) = x.overflowing_add(y as usize);
if (y >= 0) ^ overflow {
n
} else {
panic!(
"signed unsigned addition overflow: {} {}",
x,
y,
)
}
}
Это использует тот факт, что такое дополнение, если рассматривать его с точки зрения чисел без знака, должно «переполняться» (т. Е. Демонстрировать поведение дополнения к двум) только тогда, когда число без знака отрицательно, и если оно этого не делает, когда число отрицательно, это указывает на недостаточный поток.