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
的最大值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 是正确的。
由于您正在尝试计算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。
该公式适用于amount_bits最多 64,因为您在 a 中计算结果i128,该结果对于 来说足够大2\xe2\x81\xb6\xe2\x81\xb4,但它在 128 时溢出。
通过一些简单的数学运算,您可以将其更改为:
\nfn 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}\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n