Как добавить целое число со знаком к целому без знака в Rust? - PullRequest
0 голосов
/ 24 ноября 2018

Должен ли я переходить по знаку целого числа со знаком, как в примере ниже?(В реальной программе y рассчитывается для изменения индекса, указывающего на массив 64 КБ, и обходное поведение - желаемое поведение)

fn main() {
    let mut x: u16 = 100;
    let y: i8 = -1;
    //x += y;
    if y < 0 {
        x -= i8::abs(y) as u16;
    } else {
        x += i8::abs(y) as u16;
    }
    println!("{}", x);
}

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

В реальной программе y рассчитывается для изменения индекса, указывающего на массив 64 КБ, и желаемое поведение - обтекание)

Нет единого мнения о том, как все должно бытьготово, но вот мой совет: предоставьте пользователю две функции:

fn add(&mut self, index: u16) -> u16 { // return previous index why not
    // ..
}

fn sub(&mut self, index: u16) -> u16 {
    // ..
}

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

fn offset(&mut self, offset: i16) -> u16 {
    // ..
}

Цель состоит в том, чтобыпользователь должен знать, когда использовать sub или add, пользователь должен управлять только неподписанным типом.Этот вопрос ориентирован на мнение, поэтому я понимаю, если люди не согласны.

Полный пример:

use std::mem;

#[derive(Debug, PartialEq, PartialOrd)]
struct MyIndex {
    index: u16,
}

impl MyIndex {
    fn new(index: u16) -> Self {
        Self { index }
    }

    fn add(&mut self, index: u16) -> u16 {
        let index = self.index.wrapping_add(index);
        self.replace(index)
    }

    fn sub(&mut self, index: u16) -> u16 {
        let index = self.index.wrapping_sub(index);
        self.replace(index)
    }

    fn offset(&mut self, offset: i16) -> u16 {
        if offset > 0 {
            self.add(offset as u16)
        } else {
            self.sub(offset as u16)
        }
    }

    fn replace(&mut self, index: u16) -> u16 {
        mem::replace(&mut self.index, index)
    }
}

fn main() {
    let mut index = MyIndex::new(42);

    let mut other_index = MyIndex::new(84);

    let (x, first) = if index > other_index {
        (index.index - other_index.index, true)
    }
    else {
        (other_index.index - index.index, false)
    };

    // ...

    if first {
        index.sub(x);
    }
    else {
        other_index.sub(x);
    }
    println!("{:?} {:?}", index, other_index);

    index.sub(21);
    println!("{:?}", index);

    index.offset(-1);
    println!("{:?}", index);
}
0 голосов
/ 24 ноября 2018
  • Подписанные целые числа являются дополнением к двум
  • Числовой знак приведения расширяет i8 as u16

Это означает, что вы можете разыграть y as u16, оно превратится в значение дополнения к двумчто wrapping_add будет правильно обрабатывать, если y было отрицательным.

Короче говоря: делайте так, как сказал @Veedrac.

fn main() {
    let mut x: u16 = 100;
    let y: i8 = -1;
    x = x.wrapping_add(y as u16);
    println!("{}", x);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...