Reputation: 13
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()
}
Good day, I started to study Rust and came across an error (thread 'main' panicked at 'attempt to multiply with overflow'). I cannot understand why the number "2 to the power of 128" does not fit into the type 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)
Process finished with exit code 101
Upvotes: 1
Views: 185
Reputation: 29981
The maximum value of i128
is indeed 2¹²⁷-1
, which is is smaller than 2¹²⁷
. So “2 to the power of 127" does not fit into the type i128” is correct.
Since you're trying to compute x.pow(amount_bits - 1) - 1
, you need to first compute x.pow(amount_bits - 1)
, and that tries to compute 2¹²⁷
. All intermediate values also need to fit in i128
, not just the final result. Similarly, you're trying to compute -x.pow(amount_bits - 1)
, which first need to compute x.pow(amount_bits - 1)
which again, does not fit in a i128
.
That formula works fine for amount_bits
up to 64, since you compute the result in a i128
, which is big enough for 2⁶⁴
, but it overflows at 128.
With a bit of trivial math you you change to:
fn diapason(amount_bits: u32) -> [i128; 2] {
let x:i128 = 2;
[-2*x.pow(amount_bits - 2), 2*(x.pow(amount_bits - 2) - 1) + 1]
}
which does yield the expected result.
These use the following bit of trivial math, whose intermediate results are smaller and never overflow an i128:
-2**n == -2*(2 ** (n-1))
2**n-1 == 2**n - 2 + 1 == 2*(2 ** (n-1) - 1) + 1
Upvotes: 5
Reputation: 5635
The maximum value a i128 can store is 2127 - 1, and the minimum is -(2127). The first bit is used for tracking if the number is negative, leaving the remaining 127 bits to represent the actual number. 2127 values are used to represent negative numbers, 1 value is used to represent zero, and the remaining 2127 - 1 values are used to represent positive numbers. When evaluating -x.pow(amount_bits - 1)
, the negation is done after calculating the power. 2127 is 1 greater than the maximum value of an i128, so it panics. While the result would be in bounds if it got to doing the negation, Rust panics before the negation can even occur.
The simplest solution would be to use the i128::{MAX, MIN}
constants instead of manually calculating them. Alternatively, you could use a library that supports arbitrary-sized numbers, such as num
.
Upvotes: 3