可以将BigInteger截断为Rust中的i32吗?

Raj*_*jan 2 biginteger rust

在Java中,intValue()返回BigInteger实例的截断部分.我在Rust中写了一个类似的程序,但似乎没有截断:

extern crate num;

use num::bigint::{BigInt, RandBigInt};
use num::ToPrimitive;

fn main() {
    println!("Hello, world!");
    truncate_num(
        BigInt::parse_bytes(b"423445324324324324234324", 10).unwrap(),
        BigInt::parse_bytes(b"22447", 10).unwrap(),
    );
}

fn truncate_num(num1: BigInt, num2: BigInt) -> i32 {
    println!("Truncation of {} is {:?}.", num1, num1.to_i32());
    println!("Truncation of {} is {:?}.", num2, num2.to_i32());
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

Hello, world!
Truncation of 423445324324324324234324 is None.
Truncation of 22447 is Some(22447).
Run Code Online (Sandbox Code Playgroud)

我如何在Rust中实现这一目标?我应该尝试转换String然后手动截断吗?这将是我最后的选择.

ken*_*ytm 8

Java intValue()返回整数的最低32位.这可以通过按位AND操作来完成x & 0xffffffff.一BigInt在锈不支持位操作,但你可以先将其转换为一个BigUint支持这样的操作.

fn truncate_biguint_to_u32(a: &BigUint) -> u32 {
    use std::u32;
    let mask = BigUint::from(u32::MAX);
    (a & mask).to_u32().unwrap()
}
Run Code Online (Sandbox Code Playgroud)

只有当它不是负数时,转换BigIntBigUint成功.如果BigInt是负数(-x),我们可以找到其绝对值(x)的最低32位,然后否定结果.

fn truncate_bigint_to_u32(a: &BigInt) -> u32 {
    use num_traits::Signed;

    let was_negative = a.is_negative();
    let abs = a.abs().to_biguint().unwrap();
    let mut truncated = truncate_biguint_to_u32(&abs);
    if was_negative {
        truncated.wrapping_neg()
    } else {
        truncated
    }
}
Run Code Online (Sandbox Code Playgroud)

演示

truncate_bigint_to_u32(a) as i32如果您需要签名号码,可以使用.


还有一种to_signed_bytes_le()方法可以直接提取字节并将其解码为原始整数:

fn truncate_bigint_to_u32_slow(a: &BigInt) -> u32 {
    let mut bytes = a.to_signed_bytes_le();
    bytes.resize(4, 0);
    bytes[0] as u32 | (bytes[1] as u32) << 8 | (bytes[2] as u32) << 16 | (bytes[3] as u32) << 24
}
Run Code Online (Sandbox Code Playgroud)

与上述方法相比,此方法非常慢,我不建议使用它.