How to represent numbers in Rust?
Last updated
Last updated
Modern computers (CPU level) support two types of numbers. Bounded integers and Floating point numbers. Programming languages like C and Rust supports both signed(Integers that we learned in Math) and unsigned(Natural numbers) integers.
Integer examples
The integer variants signed and unsigned are available from 8, 16, ..., 128 in rust. u32 means it uses 32 bits to store the unsigned integer. It can represent 2^32 numbers from 0 to 2^32 - 1.
Floating point examples
There are only 2 variants of floating point numbers are supported in rust f32 and f64. You can read more about them . This crazy with parseInt function can be a food for thought as well.
In Rust we cannot mix numbers of different types together in a single expression.
Examples
Numbers are copyable in Rust, meaning we can do the following.
Any type that owns data on the heap is typically moved. In this case, a String is actually a smart pointer to heap data which stores UTF-8 valid bytes. So when the pointer is passed as an argument, ownership of the heap data is moved from the variable in main
to the variable s
in calculate_length
. A new copy of the pointer is being made in calculate_length
and then ownership of the heap data is given to that new pointer. In Rust, only one variable can have ownership of heap data at any given time. This concept of a single owner is how Rust efficiently manages memory. Whenever that owner goes out of scope, Rust knows that it can safely clear the data owned in memory as well.
For numbers we know exactly how many bits are required to store them. Can the same be said about Strings? The length of a String is unbounded, essentially it can be any large number only bounded by the amount of RAM of the computer. So if a length of a String is 1,000,000 then it effectively requires 8,000,000 bits plus some additional bits to store them in memory. Is it efficient to copy them in every assignment and function call?
In Rust we can create our own type. So if we can deterministically say how many bits will be required to store them in memory then we can implement Copy trait for that type, else it should obey the move semantics.
The rule is If all the members of the struct are copyable then the struct can be copyable.
Another example shows that we can pass x
as an argument to a function and continue to use x
in our current function.
We won't be able to do this for non-copyable types, like a String. There are different semantics because of the ownership rule. Take a look at the example below.