Example code:

use num_bigint::BigUint;
use num_traits::identities::One;

fn main() {
    // Example: 10001 (17) => 1110 (14)
    let n = BigUint::from(17u32);
    println!("{}", n);
    // BigUint doesn't support `!`
    //let n = !n;
    let mask = (BigUint::one() << n.bits()) - 1u32;
    let n = n ^ mask;
    println!("{}", n);
}

上面的代码使用位掩码对BigUint进行二进制补码.问题:

  1. 有没有比掩码更好的二进制补码方法?似乎BigUint不包括!运算符(但掩码可能无论如何都是必需的,这取决于!是如何定义的).
  2. 如果没有,有没有更好的方法来生成掩码?(缓存掩码很有帮助,但会占用大量内存.)

关于我实际看到的问题的更多背景:binary complement sequences

如果你交替地乘以3和位翻转一个数字,就会出现一些有趣的序列.以3开头的示例:

0. 3 (11b)  => 3*3 = 9 (1001b) => bit complement is 6 (0110b)
1. 6 (110b)
2. 13 (1101b)
3. 24 (11000b)
4. 55 (110111b)
5. 90 (1011010b)
6. 241 (11110001b)
7. 300 (100101100b)
8. 123 (1111011b)
9. 142 (10001110b)
11. 85 (1010101b)
12. 0 (0b)

一个问题是,对于所有的起始数字,它是否都为零.有些人在达到零之前徘徊了很长一段时间(425720需要87,037,147,316次迭代才能达到0).能够有效地计算这一点有助于回答这些问题.不过,大多数情况下,我还是学到了一些Rust 的东西.

推荐答案

如果你想要的是性能,num-bigint可能是isn't the best choice.然而,所有真正高性能的东西似乎都是GPL许可的.

无论哪种方式,这里有一个使用rug库的解决方案,它直接支持!(不支持),而且似乎真的很快:

use rug::{ops::NotAssign, Integer};

fn main() {
    // Example: 10001 (17) => 1110 (14)
    let mut n = Integer::from(17u32);
    println!("{}", n);
    n.not_assign();
    n.keep_bits_mut(n.significant_bits() - 1);
    println!("{}", n);
}
17
14

请注意,not_assign还会反转符号位.我们可以通过keep_bits_mut函数删除该位.


例如,以下是您的算法的一个版本:

use rug::{ops::NotAssign, Integer};

fn step(n: &mut Integer) {
    *n *= 3;
    n.not_assign();
    n.keep_bits_mut(n.significant_bits() - 1);
}

fn main() {
    let mut n = Integer::from(3);
    println!("{}", n);
    while n != 0 {
        step(&mut n);
        println!("{}", n);
    }
}
3
6
13
24
55
90
241
300
123
142
85
0

Rust相关问答推荐

在rust中如何修改一个盒装函数并将其赋回?

关于Rust 中回归的逻辑

在Rust中,在实现特征`Display`时,如何获取调用方指定的格式?

为什么铁 rust S似乎有内在的易变性?

Trait bound i8:来自u8的不满意

为什么`str`类型可以是任意大小(未知大小),而`string`类型的大小应该是已知的?

在Rust中克隆源自INTO_ITER()的迭代器的成本?

什么是`&;[][..]`铁 rust 里的刻薄?

如何限制 GtkColumnView 行数

通过写入 std::io::stdout() 输出不可见

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

在 Rust 中查找向量中 dyn struct 的索引

Rust Redis 中的 HSET 命令问题

如何在 Rust 的 Hyper 异步闭包中从外部范围正确读取字符串值

产生拥有值的迭代器的 Rust 可变borrow 在循环中失败

如何展平以下嵌套的 if let 和 if 语句?

实现不消费的迭代器

为什么可以从闭包中返回私有 struct

有没有办法隐藏类型定义?

在传输不可复制的值时实现就地枚举修改