It's not possible for you to implement external traits (like Add) for external types (like floats and integers). This case could only be added directly in the standard library, specifically in core.

But Rust generally discourages mixing types in arithmetic. In C and C++, there are type promotion rules that let this work implicitly, but Rust wants you to be explicit about such type conversions.

First, remember that 1./3 can't be perfectly represented in a float. GDB tells me that bw is rounded up slightly to 0.333333343. So when we divide "4" by bw, we should actually expect to get something slightly less than 12.

First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose corresponding real type is long double.

Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.

Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.

In computing d1, the literal 4. is a double, so bw is converted to double for the division. This computes 11.999999642372142, which is then truncated by (int) to 11.

In computing d2, the literal 4 is an int, so that is converted to float to match bw. Since this has less precision, it rounds up to exactly 12.0000... -- and then (int) gives 12 as well.

I found this type-autoconversion rounding bug in a C software on GitHUB, and I made the simple example. In Rust the type-conversions are explicit, not automatic.

fn main() {
let bw: f32 = 1./3.;
let d1: i32 = (4./bw) as i32;
let d2: i32 = (4 as f32/bw) as i32;
println!("4/(1/3) --> both are 12: {} {}", d1, d2);
}

Since of this C-bug, I don't like the automatic type conversion, if the good result is important.

I wouldn't actually call this example a C bug, per se, but more of a general issue of expecting too much accuracy from floating point. It's just that C's promotion rules tend to hide the actual types used for a given computation.

The Rust equivalent to C's type promotions would be this, which also gives you 11:

let d1: i32 = (4. / bw as f64) as i32;

Note that Rust lets the type of 4. be inferred by context, either f32 or f64, whereas it's always a double in C.

While this computation in f32 and float gives the exact result you want, it's somewhat lucky that imprecise floating point rounded that way. If you try with 1./7., you'll get 27 in both cases.

By "float" I believe he was referring to floating-point types in general. So both float and double. All floating-point types lose precision and will result in weird bugs like this when you convert them to integers. The problem is just less pronounced with double since it has higher precision.

On the topic of floating point precision, there are also crates (and C libraries) that implement arbitrary precision arithmetic.

A few examples, num in pure Rust and gmp which provides bindings to gmplib. Use one of these libraries if you need accurate arithmetic results. Floating point numbers are good for approximations.