Rust Numbers
There are two numeric data types in Rust: integers and floating point numbers.
Integers are whole numbers without a decimal point. The numbers 1, 2, 42, and 1,234,567 are all examples of integers.
Floats are numbers that have a decimal point representing a fractional value. Examples include 1.2, 5.6, and 42.0. Rust can be strict about floats; floats in Rust must contain a decimal value or the compiler will throw an error.
Integers can be either signed or unsigned. Signed integers always have a positive ‘sign’; meaning that they are always positive in value. Unsigned integers can have positive or negative values.
The possible size of any number is dictated by the number of bits as well as the type. Number type is abbreviated by a letter followed by the number of bits: i32 signifies a 32 bit signed integer, u32 indicated a 32 bit unsigned integer, and f32 indicates a 32-bit floating point number.
Integers in Rust
Integers are whole numbers without a fractional (decimal) value.
There are eight integer types in Rust, and they can be divided into four signed integer types and four unsigned integer types.
Signed integers can only have a positive value, while unsigned integers can be negative or positive.
Size | Signed | Unsigned |
16 bits | i16 | u16 |
32 bits | i32 | u32 |
64 bits | i64 | u64 |
128 bits | i128 | u128 |
arch (32 or 64 bits) | isize | usize |
Signed vs. Unsigned Integers in Rust
Unsigned integers are integers that can hold a negative value. They are typically used when a variable needs to be, or may potentially be, negative in value.
However, another important factor is that signed integers can have values twice as high as those of the unsigned.
For example, an i16 ranges from 0 to 65,535 while a u16 ranges from −32,768 to 32,767. Note that 32,767 is one-half of 65,535.
Arch Integers
Rust also uses an integer size called arch, or ‘architecture’. Arch integers set a size based on the architecture of the machine.
A 32 bit machine (x86) will assign a 32 bit integer, while a 64 bit machine (x64) will assign a 64 bit value.
There are both signed (isize) and unsigned (usize) arch data types.
Floating Point Numbers in Rust
Floating point numbers have decimals. As with integers, Rust will automatically assign variables to the float type:
let my_float = 2.1;
Constants require type annotation:
const PI_FLOAT: f32 = 3.14159;
There are 32 bit (f32) and 64 bit (f64) floats. All floats are signed.
Size | Type |
32 bits | f32 |
64 bits | f64 |
Math in Rust
Rust natively supports several basic arithmetic operations, including:
- Addition
- Subtraction
- Multiplication
- Division
- Remainder
// Addition
let my_sum = 1.1 + 2.2; // Result is '3.3'
// Subtraction
let my_diff = 18.3 - 1.2; // Result is '17.1'
// Multiplication
let my_prod = 2 * 16; // Result is '32'
// Division
let my_div = 54.2 / 67.1; // Result is '0.8077496274217587'
// Remainder
let my_rem = 28 % 6; // Result is '4'
Division With Integers vs. Floats
Rust will not convert a float into an integer in order to make a calculation more accurate.
But division often results in a decimal point number, even if both operands are integers.
If both operands are of integer type, a division operation will round down to the nearest integer.
let my_div1 = 1 / 2; // Results in '0'
let my_div2 = 1.0 / 2.0 // Results in '0.5'
Operands Must Have The Same Type
Whenever a mathematical operation is performed, the operands involved must be of the same general type. For example, the following will result in an error
let my_sum = 1 + 2.0 // Results in an error
Rust will recognize the first operand (1) as an integer type and the second operand (2.0) as a floating point type. This can be rectified by adding a decimal point to the first operand:
let my_sum = 1.0 + 2.0 // No error
Rust is strict about this; even mixing and matching integer or float types will result in an error, for example trying to add an i32 and an i64.
// Attempting to add an i32 and an i64 results in an error:
let op1: i32 = 1;
let op2: i64 = 1;
let my_sum = op1 + op2;
Standard Error
expected `i32`, found `i64`
Binding Numbers to Variables and Constants in Rust
Rust will automatically assign a data type when a variable is declared, but constants require the type to be included in the declaration:
// Declaring a variable:
let my_variable = 42;
// Declaring a constant:
const MY_CONST: i32 = 42;