 # Analog of c++ std::remainder?

I looking for Rust equivalent of std::remainder.

In compare to Rust `%` and C++ `std::fmod` where `46.0 % 90.0 = 46.0`,
`std::reminder(46.0, 90.0)` gives `-44.0`.

So some crate with such functionality, or may be stdlib?

You could define this:

``````fn remainder(a: f32, b: f32) -> f32 {
let n = (a/b).round();
a - b*n
}
``````
2 Likes

No, `f64::rem_euclid(46.0, 90.0)` return `46.0` as `46.0 % 90.0`, while `std::remainder` return `-44.0`.

Maybe I'm missing something, I've not done maths since 10 years+, but would :

``````-f64::rem_euclid(90.0, 46.0);
``````

be wrong ?

I am not sure what do you mean, if you suggest to use

``````fn rust_reminder(x: f64, y: f64) { -f64::rem_euclid(y, x) }
``````

then, this would be wrong. `std::remainder(44, 90)` gives 44,
while `-f64::rem_euclid(90.0, 44.0)` gives `-2`. That is completely wrong.

@alice solution is right except when `infinity` is present and for the sign of the reamainder of -0.0.
C++ handling of inifinity seems weird to me, because it implies `0*inf = 0`.
I also suspect some differences when half-way rounding occurs.

• From cppreference: `The IEEE floating-point remainder of the division operation x/y calculated by this function is exactly the value x - n*y, where the value `n` is the integral value nearest the exact value x/y. When |n-x/y| = ½, the value `n` is chosen to be even.`
• While the `round` functions in rust rounds half-way cases away from `0.0`.

This doesn't always work correctly. For instance: `remainder(16777216.0, 3.0)` is supposed to return 1, but returns -2.

Replace `round` with `trunc`.

It works with f64 instead of f32.
In fact with f32 `a/b` is equal to 5592405.5 (it's 5592405.333 for f64) which is the halfway case. Rust goes away from 0 when rouding `a/b` so it chooses 5592406, while c++ is supposed to choose the even number (within std::remainder, round in c++ works like round in rust) 5592406 but it seems to choose 5592405 (that's odd ).

You're misintepreting the C++ spec. `std::remainder` is not supposed to do any floating point approximating. It always returns the mathematically precise answer.

The exact value is 5592405 + 1/3, the integral value nearest that is 5592405, and the answer is 16777216 - 3 * 5592405 = 1.0 precisely.

1 Like

Suffice to say from the responses above, rust's standard library does not provide this function. However, rust is typically compiled with `libm`, which does provide the function. One can link the symbol from that library if they wish.

Playground

``````mod ffi {
use std::os::raw::c_float;

extern {
pub fn remainderf(from: c_float, to: c_float) -> c_float;
}
}
fn remainder(from: f32, to: f32) -> f32 {
unsafe { ffi::remainderf(from, to) }
}

fn main() {
assert_eq!(remainder(16777216.0, 3.0), 1.0);
}
``````

(this might cause trouble when compiling to certain targets, e.g. embedded? I almost exclusively compile to x86-64 so I would not know)

If somebody really feels that this is something the standard library ought to provide, an issue can be created on the rust repository.

1 Like

Out of interest, what are some use cases for the `std::remainder` semantics? I find Rust's `rem_euclid` very useful, but don't think I've ever run into a problem where having `rem(46.0, 90.0)` yield -44.0 would be useful.

A practical use case: `std::remainder(x, 2 * pi)` will normalize an angle to between `-pi` and `pi`, that's sometimes useful.

Also `std::remainder` can always be represented exactly with no rounding error, whereas `rem_euclid` has a rounding error, e.g. `(-1.0f64).rem_euclid(2.0f64.powi(100))` will round.

3 Likes

`remainder` is one of the functions that are "required" by the IEEE 754-2008 standard, so for that reason it might make sense to add it.

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.