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?

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.

```
mod ffi {
use std::os::raw::c_float;
#[link(name = "m")]
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.