Rust 中的数据类型

1 types rust

fn diapason(amount_bits: u32) -> [i128; 2] {
    let x:i128 = 2;
    [-x.pow(amount_bits - 1), x.pow(amount_bits - 1) - 1]
}

fn signed_and_unsigned_int() {
    let set_bits:[u32; 5] = [8, 16, 32, 64, 128];

    for i in set_bits {
        println!("i{} can store [{}, {}]", i,
                 diapason(i)[0], diapason(i)[1])
    }
}

fn main() {
    signed_and_unsigned_int()
}
Run Code Online (Sandbox Code Playgroud)

美好的一天,我开始学习 Rust 并遇到了一个错误(线程“main”因“尝试与溢出相乘”而惊慌失措)。我不明白为什么数字“2 的 128 次方”不适合 i128 类型?

C:/Users/HOME/.cargo/bin/cargo.exe run --color=always --package start_learning --bin start_learning
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target\debug\start_learning.exe`
i8 can store [-128, 127]
i16 can store [-32768, 32767]
i32 can store [-2147483648, 2147483647]
i64 can store [-9223372036854775808, 9223372036854775807]
thread 'main' panicked at 'attempt to multiply with overflow', C:\Users\HOME\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\num\mod.rs:119:5
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b\/library\std\src\panicking.rs:493
   1: core::panicking::panic_fmt
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b\/library\core\src\panicking.rs:92
   2: core::panicking::panic
             at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b\/library\core\src\panicking.rs:50
   3: core::num::{{impl}}::pow
             at C:\Users\HOME\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\num\int_macros.rs:1586
   4: start_learning::diapason
             at .\src\main.rs:4
   5: start_learning::signed_and_unsigned_int
             at .\src\main.rs:12
   6: start_learning::main
             at .\src\main.rs:17
   7: core::ops::function::FnOnce::call_once<fn(),tuple<>>
             at C:\Users\HOME\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\start_learning.exe` (exit code: 101)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

进程已完成,退出代码为 101

mca*_*ton 5

的最大值i128确实是2\xc2\xb9\xc2\xb2\xe2\x81\xb7-1,它小于2\xc2\xb9\xc2\xb2\xe2\x81\xb7。因此 \xe2\x80\x9c2 的 127 次方不适合类型 i128\xe2\x80\x9d 是正确的。

\n

由于您正在尝试计算x.pow(amount_bits - 1) - 1,因此您需要首先计算x.pow(amount_bits - 1),然后尝试计算2\xc2\xb9\xc2\xb2\xe2\x81\xb7。所有中间值也需要适合i128,而不仅仅是最终结果。类似地,您正在尝试计算-x.pow(amount_bits - 1),它首先需要x.pow(amount_bits - 1)再次计算哪一个不适合i128

\n

该公式适用于amount_bits最多 64,因为您在 a 中计算结果i128,该结果对于 来说足够大2\xe2\x81\xb6\xe2\x81\xb4,但它在 128 时溢出。

\n

通过一些简单的数学运算,您可以将其更改为:

\n
fn diapason(amount_bits: u32) -> [i128; 2] {\n    let x:i128 = 2;\n    [-2*x.pow(amount_bits - 2), 2*(x.pow(amount_bits - 2) - 1) + 1]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

确实产生了预期的结果

\n

它们使用以下一些简单的数学运算,其中间结果更小并且永远不会溢出 i128:

\n
-2**n == -2*(2 ** (n-1))\n2**n-1 == 2**n - 2 + 1 == 2*(2 ** (n-1) - 1) + 1\n
Run Code Online (Sandbox Code Playgroud)\n