In PHP
PHP has one int and one float. 7 / 2 is 3.5. intdiv(7, 2) is 3. PHP_INT_MAX + 1 becomes a float. The type grows.
These values are falsy: 0, 0.0, "", "0", [], null, and false. There is no char. "é" is a string, and strlen counts bytes.
<?php
echo 7 / 2, "\n";
echo intdiv(7, 2), "\n";
$ready = "0";
if ($ready) {
echo "truthy\n";
} else {
echo "falsy\n";
}
echo strlen("é"), "\n";
That prints 3.5, then 3, then falsy, then 2.
In Rust
An unsuffixed integer is i32. An unsuffixed float is f64. A suffix picks another width (1_000_000u64, 2.5_f32). Underscores are only for reading.
isize and usize match the pointer width. A length or an index is a usize.
| 8 bits | 16 | 32 | 64 | 128 | |
|---|---|---|---|---|---|
| Signed | i8 |
i16 |
i32, the default |
i64 |
i128 |
| Unsigned | u8 |
u16 |
u32 |
u64 |
u128 |
A signed iN runs from -2^(N-1) through 2^(N-1) - 1. An unsigned uN runs from 0 through 2^N - 1. i8 is -128 through 127. u8 is 0 through 255.
Integer / truncates. 7 / 2 is 3.
In a debug build, an overflowing + panics. A release build wraps. checked_add returns None either way. Next to it, wrapping_add always wraps and saturating_add clamps at the type's min or max. The calculator uses checked_add, checked_sub, checked_mul, and checked_div so overflow and divide-by-zero both come back as None.
as between integers keeps the low bits. 300 as u8 is 44. When the value might not fit, use try_into (or TryFrom). as from a float rounds toward zero, so 300.9 as i32 is 300. A float that cannot fit saturates to the integer's min or max, and NaN becomes 0. That cast does not report the loss.
Do not compare floats with ==. 0.1 + 0.2 is not a clean 0.3. Check an explicit tolerance instead: (0.1 + 0.2 - 0.3).abs() < 1e-9. f64::EPSILON is the gap between 1.0 and the next f64, so it is not a general-purpose tolerance.
if needs a bool. A number is not a condition.
char is four bytes and one Unicode scalar value. It is not a PHP string, and it is not a grapheme cluster.
use std::f64::consts::PI;
fn main() {
let n = 42;
let width = 1.5;
let big = 1_000_000u64;
let single = 2.5_f32;
let index: usize = 0;
println!("{n} {width} {big} {single} {index}");
let quotient = 7 / 2;
println!("{quotient}");
let overflow = i32::MAX.checked_add(1);
println!("{overflow:?}");
let wide: i32 = 300;
let truncated = wide as u8;
println!("{truncated}");
let fitted: Result<u8, _> = 200i32.try_into();
let too_big: Result<u8, _> = wide.try_into();
println!("{fitted:?} {too_big:?}");
let toward_zero = 300.9_f64 as i32;
println!("{toward_zero}");
println!("{PI}");
let ready = true;
if ready {
println!("ready");
}
let letter: char = 'é';
let han: char = '中';
let bytes = size_of::<char>();
println!("{letter} {han} {bytes}");
let close = (0.1_f64 + 0.2 - 0.3).abs() < 1e-9;
println!("{close}");
}
quotient is 3. overflow is None. truncated is 44. fitted is Ok(200) and too_big is Err. toward_zero is 300. bytes is 4. close is true.
Watch for:
askeeps going when the value does not fit.try_intoreturnsErrinstead. A float compared with==will not do what the decimal looks like it should.f64::EPSILONis not a drop-in tolerance for every magnitude.
Idiomatic Rust:
checked_addwhen overflow matters, as in the calculator.wrapping_addandsaturating_addwhen you want wrap or clamp instead ofNone.usizefor an index.std::f64::consts::PIfor pi.(a - b).abs() < 1e-9(or another tolerance you choose) for float equality checks.
Side by side
| PHP | Rust | |
|---|---|---|
7 / 2 |
3.5. intdiv is 3 |
3 |
| Overflow | The int becomes a float | Debug panics, release wraps, checked_add is None |
| Narrowing | The value may change type | as truncates. try_into when it might not fit |
| Float equality | Often abs($a - $b) < 1e-9 |
(a - b).abs() < 1e-9. Not f64::EPSILON as a general tolerance |
"0" or [] in if |
Falsy | if needs a bool |
| One letter | A string. strlen("é") is 2 |
char, four bytes, one scalar |
Try it
Open src/main.rs in the Playground. Confirm 7 / 2 prints 3 and checked_add prints None. Change wide from 300 to 40 and run it again. as and try_into then agree on 40. Put 300 back: as prints 44 and try_into is Err. Confirm close prints true for the 1e-9 tolerance check.
Key takeaways
- Unsuffixed integers are
i32and unsuffixed floats aref64. Width is the number of bits.usizeis the index type. 7 / 2is3. Overflow ischecked_addwhen you need aNone. Preferwrapping_addorsaturating_addwhen wrap or clamp is the rule.astruncates.try_intofails when the integer does not fit. Compare floats with an explicit tolerance such as1e-9, not==.f64::EPSILONis not a general-purpose tolerance.boolhas no truthiness.charis one Unicode scalar, four bytes wide.
What's next: Functions and expressions