I started learning Rust. I tried this program:
fn main() { let a = 5; let b = 5.5; let k = a + b; println!("{}", k); }
and it is showing this error:
error[E0277]: cannot add a float to an integer --> src/main.rs:4:16 | 4 | let k = a + b; | ^ no implementation for `{integer} + {float}` | = help: the trait `std::ops::Add<{float}>` is not implemented for `{integer}`
Is the code wrong?
The technically correct answer is: because no one has written impl Add<f64> for i32 {}
.
The cheeky answer is: because Rust doesn't want you to shoot yourself in the foot.
The longer, potentially more useful answer is...
In computers, integers and floating point numbers both have a limited range, ultimately driven by the number of bits that we use to represent them. In Rust, the default type of an integer that isn't otherwise constrained is a i32
, and the default type of a floating point that isn't otherwise constrained is a f64
.
Integral types don't allow you to have a fractional part, and floating point types have a limited number of integers they can exactly represent. If Rust let you add these two types, it would be making a decision for you about which piece of data was less important, which is not really the kind of thing you want your systems programming language to do!
Here are the options I can see:
Of those choices, only an error is reasonable.
There's also the potential to introduce a type that can precisely handle arbitrary precision. Unfortunately, those types are no longer "cheap" for the processor to operate on, so you'd have to trade off performance.
If the programmer wishes to perform some conversion, then you can cast the value using as
or From
:
f64::from(a) + b;
a + b as i32
See also:
Veedrac adds:
[this answer gives] the impression that
0u32 + 0u64
should work, but Rust doesn't do any numeric promotions, even if promotion would be lossless. Also,i32
→f64
is a lossless promotion, sincef64
has a 52-bit mantissa.
While these types of widening promotions would indeed be lossless, they would involve implicitly increasing your memory requirements. What used to only take 32 bits now takes 64 bits, for example. Beyond the memory requirements, there's also semantic considerations. If a value should only require a u8
(0-255), then it doesn't make sense to increase it by a value that might be beyond that range. Knowing that it is appropriate to do such a transformation falls solely on the programmer.
Using From
can ensure that you only use lossless number conversion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With