@@ -1,6 +1,6 @@
|
||||
# Types, part 1
|
||||
|
||||
In the ["Syntax" section](../01_intro/01_syntax.md) `compute`'s input parameters were of type `u32`.
|
||||
In the ["Syntax" section](../01_intro/01_syntax.md) `compute`'s input parameters were of type `u32`.\
|
||||
Let's unpack what that _means_.
|
||||
|
||||
## Primitive types
|
||||
@@ -18,25 +18,25 @@ An integer is a number that can be written without a fractional component. E.g.
|
||||
|
||||
### Signed vs. unsigned
|
||||
|
||||
An integer can be **signed** or **unsigned**.
|
||||
An integer can be **signed** or **unsigned**.\
|
||||
An unsigned integer can only represent non-negative numbers (i.e. `0` or greater).
|
||||
A signed integer can represent both positive and negative numbers (e.g. `-1`, `12`, etc.).
|
||||
|
||||
The `u` in `u32` stands for **unsigned**.
|
||||
The `u` in `u32` stands for **unsigned**.\
|
||||
The equivalent type for signed integer is `i32`, where the `i` stands for integer (i.e. any integer, positive or
|
||||
negative).
|
||||
|
||||
### Bit width
|
||||
|
||||
The `32` in `u32` refers to the **number of bits[^bit]** used to represent the number in memory.
|
||||
The `32` in `u32` refers to the **number of bits[^bit]** used to represent the number in memory.\
|
||||
The more bits, the larger the range of numbers that can be represented.
|
||||
|
||||
Rust supports multiple bit widths for integers: `8`, `16`, `32`, `64`, `128`.
|
||||
|
||||
With 32 bits, `u32` can represent numbers from `0` to `2^32 - 1` (a.k.a. [`u32::MAX`](https://doc.rust-lang.org/std/primitive.u32.html#associatedconstant.MAX)).
|
||||
With 32 bits, `u32` can represent numbers from `0` to `2^32 - 1` (a.k.a. [`u32::MAX`](https://doc.rust-lang.org/std/primitive.u32.html#associatedconstant.MAX)).\
|
||||
With the same number of bits, a signed integer (`i32`) can represent numbers from `-2^31` to `2^31 - 1`
|
||||
(i.e. from [`i32::MIN`](https://doc.rust-lang.org/std/primitive.i32.html#associatedconstant.MIN)
|
||||
to [`i32::MAX`](https://doc.rust-lang.org/std/primitive.i32.html#associatedconstant.MAX)).
|
||||
to [`i32::MAX`](https://doc.rust-lang.org/std/primitive.i32.html#associatedconstant.MAX)).\
|
||||
The maximum value for `i32` is smaller than the maximum value for `u32` because one bit is used to represent
|
||||
the sign of the number. Check out the [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement)
|
||||
representation for more details on how signed integers are represented in memory.
|
||||
@@ -46,7 +46,7 @@ representation for more details on how signed integers are represented in memory
|
||||
Combining the two variables (signed/unsigned and bit width), we get the following integer types:
|
||||
|
||||
| Bit width | Signed | Unsigned |
|
||||
|-----------|--------|----------|
|
||||
| --------- | ------ | -------- |
|
||||
| 8-bit | `i8` | `u8` |
|
||||
| 16-bit | `i16` | `u16` |
|
||||
| 32-bit | `i32` | `u32` |
|
||||
@@ -55,21 +55,21 @@ Combining the two variables (signed/unsigned and bit width), we get the followin
|
||||
|
||||
## Literals
|
||||
|
||||
A **literal** is a notation for representing a fixed value in source code.
|
||||
A **literal** is a notation for representing a fixed value in source code.\
|
||||
For example, `42` is a Rust literal for the number forty-two.
|
||||
|
||||
### Type annotations for literals
|
||||
|
||||
But all values in Rust have a type, so... what's the type of `42`?
|
||||
|
||||
The Rust compiler will try to infer the type of a literal based on how it's used.
|
||||
If you don't provide any context, the compiler will default to `i32` for integer literals.
|
||||
The Rust compiler will try to infer the type of a literal based on how it's used.\
|
||||
If you don't provide any context, the compiler will default to `i32` for integer literals.\
|
||||
If you want to use a different type, you can add the desired integer type as a suffix—e.g. `2u64` is a 2 that's
|
||||
explicitly typed as a `u64`.
|
||||
|
||||
### Underscores in literals
|
||||
|
||||
You can use underscores `_` to improve the readability of large numbers.
|
||||
You can use underscores `_` to improve the readability of large numbers.\
|
||||
For example, `1_000_000` is the same as `1000000`.
|
||||
|
||||
## Arithmetic operators
|
||||
@@ -82,7 +82,7 @@ Rust supports the following arithmetic operators[^traits] for integers:
|
||||
- `/` for division
|
||||
- `%` for remainder
|
||||
|
||||
Precedence and associativity rules for these operators are the same as in mathematics.
|
||||
Precedence and associativity rules for these operators are the same as in mathematics.\
|
||||
You can use parentheses to override the default precedence. E.g. `2 * (3 + 4)`.
|
||||
|
||||
> ⚠️ **Warning**
|
||||
@@ -92,7 +92,7 @@ You can use parentheses to override the default precedence. E.g. `2 * (3 + 4)`.
|
||||
|
||||
## No automatic type coercion
|
||||
|
||||
As we discussed in the previous exercise, Rust is a statically typed language.
|
||||
As we discussed in the previous exercise, Rust is a statically typed language.\
|
||||
In particular, Rust is quite strict about type coercion. It won't automatically convert a value from one type to
|
||||
another[^coercion],
|
||||
even if the conversion is lossless. You have to do it explicitly.
|
||||
|
||||
Reference in New Issue
Block a user