Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtraction not implemented for f32?

Tags:

rust

When compiling the following code:

use std::io::*;

fn main(){
    let reader = stdin();
    let nums = reader.lock()
        .lines().next().unwrap().unwrap()
        .split_whitespace()
        .map(|s| s.parse::<i32>().unwrap())
        .map(|s| s as f32)
        .map(|s| (s - 4) / 2)
        .map(|s| s as i32)
        .collect();
}

I get an error saying:

the trait core::ops::Sub<_> is not implemented for the type f32

Why is this?

like image 386
lochnesscookie Avatar asked Jan 21 '16 00:01

lochnesscookie


1 Answers

Rust is stricter than some other languages when it comes to manipulating primitive types. Most math operators require the same type on both sides (with the exception of bit shifts, which expect a usize as the right-hand side operand). Rust will not automatically cast values from one primitive numeric type to another: you must insert an explicit cast in the code. This code demonstrates the situation:

fn main(){
    let a: i32 = 2;
    let b: i8 = 3;
    println!("{}", a + b);
}

It fails to compile with the following errors:

<anon>:4:24: 4:25 error: mismatched types:
 expected `i32`,
    found `i8`
(expected i32,
    found i8) [E0308]
<anon>:4     println!("{}", a + b);
                                ^
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:4:5: 4:27 note: in this expansion of println! (defined in <std macros>)
<anon>:4:24: 4:25 help: see the detailed explanation for E0308
<anon>:4:20: 4:25 error: the trait `core::ops::Add<i8>` is not implemented for the type `i32` [E0277]
<anon>:4     println!("{}", a + b);
                            ^~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:4:5: 4:27 note: in this expansion of println! (defined in <std macros>)
<anon>:4:20: 4:25 help: see the detailed explanation for E0277

Your situation is similar, but it has the particularity that you're mixing integers and floats. In Rust, integer and float literals are assigned a type based on context. That's why I could set a to 2 and b to 3 above: 2 is not always an i32, but it is implicitly typed as i32 if the context requires it.

In your case, you're trying to subtract an integer from an f32. The error message mentions Sub<_>; that _ represents the type of the 4 literal that the compiler wasn't able to figure out.

The solution is simply to use float literals instead of integer literals:

use std::io::*;

fn main(){
    let reader = stdin();
    let nums = reader.lock()
        .lines().next().unwrap().unwrap()
        .split_whitespace()
        .map(|s| s.parse::<i32>().unwrap())
        .map(|s| s as f32)
        .map(|s| (s - 4.0) / 2.0)
        .map(|s| s as i32)
        .collect::<Vec<_>>();
}
like image 191
Francis Gagné Avatar answered Sep 18 '22 14:09

Francis Gagné