Add, Mul not implemented for f64 + usize

I have a general algorithm for calculating the weighted mean that "should" work for almost anything that can be multiplied, divided and added together.

However when trying to send an iterator of floats (f64), I was surprised that it doesn't implement Mul and Div with usize. Does anyone know the reason behind it (I understand that f32 cannot represent every u32, but is this the case for f64 as well?) Is there any easy workaround for this?

Due to the orphan rule, I cannot "just" implement Mul and Div for f64...

pub fn weighted_mean<T: Mul<usize, Output = T> + Add<Output = T> + Div<usize, Output = T> >(input: impl IntoIterator<Item = (T, usize)>) -> T {
  let mut iter = input.into_iter();
  let first = iter.next().expect("a non-empty iterator");
  let (weighted_sum, total_weight) = iter.fold((first.0 * first.1, first.1), |(weighted_sum, total_weight), item| (item.0 * item.1 + weighted_sum, total_weight + item.1));
  weighted_sum / total_weight
}

Rust only implements math operators when both sides are the same type. Otherwise, you run into problems with type inference where the compiler is often unable to figure out what integer type something should be.

No, but you can cast your usize to f64 and perform the division.

1 Like

Ah, gotcha.

Well most general I could do is this, but the compiler is not smart enough to figure out all type params unfotunately, and at least the first parameter needs to be supplied.

pub fn weighted_mean<Size, T, U>(input: impl IntoIterator<Item = (T, U)>) -> T where T: Mul<Size, Output = T> + Add<Output = T> + Div<Size, Output = T>, U: Copy + Into<Size> + Add<Output = U>  {
  let mut iter = input.into_iter();
  let first = iter.next().expect("a non-empty iterator");
  let (weighted_sum, total_weight): (T, U) = iter.fold((first.0 * first.1.into(), first.1), |(weighted_sum, total_weight), item| (item.0 * item.1.into() + weighted_sum, total_weight + item.1));
  weighted_sum / total_weight.into()
}

This works for (f64, u32) for example, if called with weighted_mean<f64, _, _>(..)

I would probably just hard-code the number types.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.