代码之家  ›  专栏  ›  技术社区  ›  Rajeev Ranjan

一个大整数可以被截断为i32吗?

  •  2
  • Rajeev Ranjan  · 技术社区  · 6 年前

    在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;
    }
    

    我从中得到的结果是

    Hello, world!
    Truncation of 423445324324324324234324 is None.
    Truncation of 22447 is Some(22447).
    

    我怎样才能在铁锈中做到这一点?我应该换成 String 然后手动截断?这是我最后的选择。

    2 回复  |  直到 6 年前
        1
  •  8
  •   Shepmaster Tim Diekmann    6 年前

    爪哇 intValue() 返回整数的最低32位。这可以通过按位和操作来完成。 x & 0xffffffff . 一 BigInt in Rust 不支持按位操作,但可以先将其转换为 BigUint 哪一个 supports 这样的行动。

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

    转换 大整数 偏执的 只有当它不是负数时才会成功。如果 大整数 为负(-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
        }
    }
    

    Demo

    你可以用 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
    }
    

    与上面的方法相比,这个方法非常慢,我不建议使用它。

        2
  •  3
  •   Denys Séguret    6 年前

    大整数不会自然地截断为小整数。要么适合,要么你必须决定你想要什么价值。

    你可以这样做:

    println!("Truncation of {} is {:?}.", num1, num1.to_i32().unwrap_or(-1));
    

    println!("Truncation of {} is {:?}.", num1, num1.to_i32().unwrap_or(std::i32::MAX));
    

    但是,当返回的选项不包含值时,应用程序逻辑可能会指示所需的行为。