How to multiply/divide/add/subtract numbers of different types?
TL;DR: as
is the most common way to convert between the primitive numeric types but using it requires thinking.
fn c_to_f(c: f32) -> f32 {
(c * (9 as f32 / 5 as f32)) + 32 as f32
}
In this example though, it's more reasonable to just use floating point literals to start with:
fn c_to_f(c: f32) -> f32 {
(c * (9. / 5.)) + 32.
}
The real problem is that doing mixed type arithmetic is a bit complicated.
If you are multiplying1 a T
by a T
, you generally expect to get a result of type T
, at least with the basic types.
When mixing types, however, there are some difficulties:
- mixing signedness,
- mixing precision.
So, for example, what is the ideal result of i8 * u32
? The smallest type that can encompass the full set of all i8
and u32
values is a i64
. Should that be the result?
As another example, what is the ideal result of f32 * i32
? The smallest type that can encompass the full set of all f32
and i32
values is a f64
. Should that be the result?
I find the idea of having a such widening rather confusing. It also has performance impacts (operations on f32
can be much speedier than operations on f64
, once vectorized).
Due to those issues, Rust for now requires you to be explicit: which type do you want the computation to be carried in? Which type makes sense for your particular situation?
And then cast appropriately, using as
, and do think about which rounding mode to apply (.round()
, .ceil()
, .floor()
or .trunc()
when going from floating point to integral).
1 Adding, Subtracting and Dividing work in similar ways.
![Kenny Worden](https://i.stack.imgur.com/B4jsh.jpg?s=256&g=1)
Kenny Worden
Updated on June 13, 2022Comments
-
Kenny Worden about 2 years
I'm working through the second edition of the Rust handbook, and decided to try and make the classic Celsius-to-Fahrenheit converter:
fn c_to_f(c: f32) -> f32 { return ( c * ( 9/5 ) ) + 32; }
Compiling this with
cargo build
will yield the compile-time error:error[E0277]: the trait bound `f32: std::ops::Mul<{integer}>` is not satisfied --> src/main.rs:2:12 | 2 | return (c * (9 / 5)) + 32; | ^^^^^^^^^^^^^ the trait `std::ops::Mul<{integer}>` is not implemented for `f32` | = note: no implementation for `f32 * {integer}`
As a new Rust programmer, my interpretation is that I cannot multiply float and integer types together. I solved this by making all of my constants floating points:
fn c_to_f(c: f32) -> f32 { return ( c * ( 9.0/5.0 ) ) + 32.0; }
This leaves me with reservations. Coming from C/C++/Java/Python, it was surprising to learn that you cannot simply perform arithmetic on numbers of different types. Is the right thing to simply convert them to the same type, as I did here?