如何交换两个变量?

时间:2015-08-04 00:13:25

标签: rust

这个Python代码最接近的等效Rust代码是什么?

a, b = 1, 2
a, b = b, a + b

我正在尝试编写一个迭代的Fibonacci函数。我有Python代码我想转换为Rust。一切都很好,除了交换部分。

def fibonacci(n):
    if n < 2:
        return n
    fibPrev = 1
    fib = 1
    for num in range(2, n):
        fibPrev, fib = fib, fib + fibPrev
    return fib

3 个答案:

答案 0 :(得分:21)

交换变量时,您最想要的是为ab创建新的绑定

fn main() {
    let (a, b) = (1, 2);
    let (b, a) = (a, a + b);
}

但是,在您的实际情况中,没有一个很好的解决方案。如上所述,您始终为ab创建新绑定,但您想要修改现有绑定。我所知道的一个解决方案是使用临时的:

fn fibonacci(n: u64) -> u64 {
    if n < 2 {
        return n;
    }
    let mut fib_prev = 1;
    let mut fib = 1;
    for _ in 2..n {
        let next = fib + fib_prev;
        fib_prev = fib;
        fib = next;
    }
    fib
}

你也可以这样做,以便改变元组:

fn fibonacci(n: u64) -> u64 {
    if n < 2 {
        return n;
    }
    let mut fib = (1, 1);
    for _ in 2..n {
        fib = (fib.1, fib.0 + fib.1);
    }
    fib.1
}

您可能还有兴趣交换两块内存的内容。在99%以上的时间里,你想要重新绑定变量,但只需要很短的时间来“改变”“

fn main() {
    let (mut a, mut b) = (1, 2);
    std::mem::swap(&mut a, &mut b);

    println!("{:?}", (a, b));
}

请注意,执行此交换并不简洁,只需一步即可将这些值相加。

另见:

答案 1 :(得分:5)

此外,在Rust中实现Fibonacci序列的更好方法是使用Iterator特征:

// Iterator data structure
struct FibIter(u32, u32);

// Iterator initialization function
fn fib() -> FibIter {
    FibIter(0u32, 1u32)
}

// Iterator trait implementation
impl Iterator for FibIter {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        *self = FibIter(self.1, self.1 + self.0);
        Some(self.0)
    }
}

fn main() {
    println!("{:?}", fib().take(15).collect::<Vec<_>>());
}

参见 The Rust Programming Language chapter on iterators

答案 2 :(得分:1)

我很惊讶没有答案提到XOR-swap

fibPrev ^= fib;
fib ^= fibPrev;
fibPrev ^= fib;

这是一种众所周知的交换两个值而无需使用临时变量或冒整数溢出风险的方法。

请注意,对于现代优化的编译器,在大多数情况下,从性能的角度来看,最好只使用一个临时变量(请参阅trentcl在注释中的链接)。但是,XOR交换有一些用例,链接的Wikipedia文章对它的优缺点提供了不错的概述。

很有意思的是,如果您要在rust中实现XOR交换作为函数,则无需检查是否要与自身交换变量(在这种情况下,您最终会得到它)由于XOR运算的属性而被设置为零)。比较rust中的交换实现:

fn swap(a: &mut i32, b: &mut i32) {
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

和C ++:

void swap(int& a, int& b) {
    if (&a == &b) return; // Avoid swapping the variable with itself
    a ^= b;
    b ^= a;
    a ^= b;
}

如果您尝试在rust中这样调用swap:

let mut a = 42;
swap(&mut a, &mut a);

您将收到编译错误:

error[E0499]: cannot borrow `a` as mutable more than once at a time
  --> src/main.rs:27:18
   |
27 |     swap(&mut a, &mut a);
   |     ---- ------  ^^^^^^ second mutable borrow occurs here
   |     |    |
   |     |    first mutable borrow occurs here
   |     first borrow later used by call