Ben Chuanlong Du's Blog

It is never too late to learn.

Primitive Types in Rust

In [ ]:
:timing
:sccache 1

Tips

  • Integer types:
    • u8 (0 to 255),
    • i8 (-128 to 127),
    • u16 (0 to 65,535),
    • i16 (-32,768 to 32,767),
    • u32 (0 to 4,294,967,295),
    • i32 (-2,147,483,648 to 2,147,483,647),
    • u64,
    • i64.
      Notice that i32 is the default type for integers.
  • Float types: f32, f64 (default)
  • Boolean: bool
  • Character: char
  • Tuple
  • Array

Type Cast

  • Cast without loss using type::from or obj.into.
  • cast with possible loss using as
  • Implementing From will result in the Into implementation but not vice-versa.

For more discussions, please refer to How do I convert between numeric types safely and idiomatically?.

From and Into

Why From trait vs Into trait?

Cast a smaller integer to a larger integer

Number Conversions

Integers

In [2]:
0xFFFF as u8
0xFFFF as u8
^^^^^^ 
literal out of range for `u8`
help: consider using the type `u16` instead
In [3]:
let x: i64 = 1;
i32::from(x)
i32::from(x)
^^^^^^^^^ the trait `From<i64>` is not implemented for `i32`
the trait bound `i32: From<i64>` is not satisfied
help: the following implementations were found:
  <i32 as From<NonZeroI32>>
  <i32 as From<bool>>
  <i32 as From<i16>>
  <i32 as From<i8>>
and 2 others
In [6]:
let x: usize = 1;
u64::from(x)
u64::from(x)
^^^^^^^^^ the trait `From<usize>` is not implemented for `u64`
the trait bound `u64: From<usize>` is not satisfied
help: the following implementations were found:
  <u64 as From<NonZeroU64>>
  <u64 as From<bool>>
  <u64 as From<u16>>
  <u64 as From<u32>>
  <u64 as From<u8>>
In [5]:
let x: u64 = 1;
u64::from(x)
Out[5]:
1
In [2]:
let x: i64 = 1;
x
Out[2]:
1
In [4]:
x as i32
Out[4]:
1
In [5]:
let x1: u8 = 1;
x1
Out[5]:
1
In [7]:
let x2: i8 = 1;
x2
Out[7]:
1
In [10]:
let x3: i32 = 1;
x3
Out[10]:
1

Comparison and Ordering

Ordering::Less, Ordering::Equal and Ordering::Greater are converted to -1, 0 and 1 when converting an Ordering enum to an integer.

In [3]:
1.cmp(&2)
Out[3]:
Less
In [4]:
1.cmp(&2) as i32
Out[4]:
-1
In [5]:
2.cmp(&2) as i32
Out[5]:
0
In [6]:
3.cmp(&2) as i32
Out[6]:
1

Type Suffix for Literal Integers

In [8]:
1 << 54
1 << 54
^^^^^^^ attempt to shift left by `54_i32`, which would overflow
this arithmetic operation will overflow
In [9]:
1u64 << 54
Out[9]:
18014398509481984

Bit Operations on Integers

  1. Mathematic operators +, -, * and / have high precedence than bit operators (&, |, !, ^, <<, >>, etc)!!! It is suggested that you use parentheses if you are not sure about the precedences.
In [10]:
let x: u64 = (1u64 << 52) - 1;
x
Out[10]:
4503599627370495
In [11]:
format!("{:b}", x)
Out[11]:
"1111111111111111111111111111111111111111111111111111"
In [2]:
i32::from(1)
Out[2]:
1

count_ones

Count ones in an integer.

In [11]:
let n: u64 = 0b100_0000;
n.count_ones()
Out[11]:
1
In [2]:
2i16 << 1
Out[2]:
4
In [3]:
-2i16 << 1
Out[3]:
-4
In [5]:
let mut x = -10i16;
x <<= 1;
x
Out[5]:
-20

Floating Numbers

NaN Is Tricky

In [2]:
f64::NAN
Out[2]:
NaN
In [3]:
1.0 > f64::NAN
Out[3]:
false
In [4]:
1.0 == f64::NAN
Out[4]:
false
In [5]:
1.0 < f64::NAN
Out[5]:
false
In [6]:
1.0 + f64::NAN
Out[6]:
NaN

tuple

In [3]:
let t = (1, "hello");
t
Out[3]:
(1, "hello")
In [ ]:

Comments