Ceiling of isize/isize


#1

We have:

x: isize;
y: isize

I want to compute ceiling of (x/y).

Is the best way to do this via:

((x as f32) / (y as f32)).ceil() as isize

In a language like C, I’d do int ans = ceil(1.0*x/y) without much thought, but here with all the as casting going no, I’m wondering if there is a better way.


#2

Floating point is unnecessary. You can just use integer division in both Rust and C: (x-1)/y + 1. (See my correction below, thanks to @zeroexcuses.)


#3

Does isize/isize truncate to 0 or to lower value? Where is this documented in the rust spec?


#4

Ah, whoops, you’re right. It truncates to 0. This is also mentioned in the docs for std::ops::Div under impl Div<usize> for usize.

You would have to treat unmatched signs differently. It’s best to put this into a helper extension-trait method so that you can invoke x.div_ceil(y). You could also ask the num crate maintainers to add it to their Integer trait.

Though, using the num crate’s Integer trait, you could use div_floor and use the formula above: (x-1).div_floor(y) + 1. Actually, comes to think of it, -(-x).div_floor(y) is even shorter (since floor is the opposite of ceil).


#5

Note that the f32 approach will produce incorrect (approximated) results for large enough numbers. f64 should be precise for all 32-bit integers, but if isize is 64-bit then there’s no way to do it fully correctly with floating point.


#6

@marcianx , @comex : Thanks for the insights. I’m going to go with the f64 approach (seems most obvious what the code is doing, even if it’s verbose.)


#7

Does this work ? I actually more worry about the performance issue caused by floating division

x/y + if x % y != 0 { 1 } else { 0 } 

https://godbolt.org/z/Cw0UAc