Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't the absolute value methods on signed integers return unsigned values?

Tags:

rust

The following code fails to compile:

fn main() {
    let x = (-5i32).abs();

    let z: u32 = x;
}

with the message:

error[E0308]: mismatched types
 --> src/main.rs:4:18
  |
4 |     let z: u32 = x;
  |                  ^ expected u32, found i32

Reading the documentation, it looks the choice of i32 stems from the fact that i32::min_value() has no positive representation in i32. However, it would have a positive representation in u32, which can represent numbers twice as large.

I'm learning the language, and want to understand why certain design decisions were made so that I can develop good habits. I find this one confusing. Can someone explain why it works this way instead of just returning a u32, which would seem to be the semantically correct type?

like image 534
John Doucette Avatar asked Aug 08 '18 18:08

John Doucette


People also ask

Can signed integers represent more values than unsigned integers?

Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large. An n-bit unsigned variable has a range of 0 to (2n)-1.

Can signed variables be converted to unsigned?

To convert a signed integer to an unsigned integer, or to convert an unsigned integer to a signed integer you need only use a cast. For example: int a = 6; unsigned int b; int c; b = (unsigned int)a; c = (int)b; Actually in many cases you can dispense with the cast.

What is the difference between unsigned and signed integer?

A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.

Does ABS return an int?

In a C program, abs always takes and returns an int .


1 Answers

There's a link to the development meeting minutes where this was discussed in the proposed RFC "Change abs() to return unsigned integers"

It looks like the main reasons were:

  1. Many other languages use i32 -> i32 (for instance, C, Java), because the accidental promotion of other values to u32 might cause bugs. Rust seems to have used i32 -> i32 for this reason originally (i.e. following convention), but doesn't suffer from the same kinds of bugs.
  2. This feature request wasn't submitted until after Rust had reached beta. The developers were not willing to introduce a breaking change to the language over what appears to be a rare bug. This looks like the main reason offered for keeping things this way.

It seems like the accepted workaround is to use as u32 to cast.

i32::overflowing_abs i32::wrapping_abs and i32::checked_abs implement other solutions to the i32::min_value() bug, but none of them produces a u32.

like image 153
John Doucette Avatar answered Oct 13 '22 19:10

John Doucette