in python
-1 % 200 ===> 199
but in rust
-1 % 200 ===> -1
???
and how can i get the same result with python? ![]()
in python
-1 % 200 ===> 199
but in rust
-1 % 200 ===> -1
???
and how can i get the same result with python? ![]()
It's possible to use rem_euclid method of integer types (which computes least nonnegative remainder) to have the same behavior as in Python, for example:
(-1i32).rem_euclid(200)
Will provide 199 as an answer.
Python does provide math.remainder which computes truncated remainder like % operator in Rust does, however this particular function takes floating point numbers, and so won't work well with large integers.
I cannot answer to “why” cuz I’m not some kinda Python expert, but I can tell you “how”. You can use PyO3 with maturin to build something like this:
use pyo3::prelude::*;
#[pyfunction]
fn rem(x: i32, y: i32) -> PyResult<i32> {
Ok(x % y)
}
#[pymodule]
fn remainder(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(rem, m)?)?;
Ok(())
}
then install your package / extract a pyd and use it like this
from remainder import rem
print(f'{rem(-1, 200)}')
This probably is not the best way and maybe there are some mistakes in my examples, but I hope you got the point ![]()
thanks ! ![]()
I did some research. Python’s % is actually a modulo operator, while Rust’s % is just a remainder. So, as @xfix said, you need rem_euclid method.
There are three common variants of this:
Truncating division.
a / b computes round_towards_0(a / b).
a % b has the same sign as a.
This is what Rust and C use.
Flooring division.
a / b computes floor(a / b).
a % b has the same sign as b.
This is what Python uses.
Euclidean division.
a / b = round_down(a) / b
a % b is always nonnegative.
This is what Rust uses with a.div_euclid(b), a.rem_euclid(b).
#3 has the nicest mathematical properties, #2 second-nicest, #1 is more-less unusable for negative numbers if you care about the remainder.
I think Rust just copied the #1 behavior from C. And C copied it from the hardware division instruction on many CPUs (idiv). I think this is a design mistake, because:
idiv is slow and fixing its output doesn't cost many cyclesidiv doesn't have to be usedIf you divide by 200, both % and rem_euclid use imul twice rather than idiv, with rem_euclid using a few additional instructions. godbolt
If you divide by 16, both use and, with rem_euclid using a few fewer instructions. The latter improved in Rust 1.65, probably thanks to this LLVM improvement.