top | item 43014353

(no title)

cashsterling | 1 year ago

Rust has functionality in the std lib for saturating arithmetic (and other kinds of arithmetic via crates) so that calculations saturate rather than overflow, etc. https://doc.rust-lang.org/nightly/std/?search=saturating

discuss

order

throwaway81523|1 year ago

From what I can tell, you have to do special crap in Rust to deal with overflow. Saturating is almost never what you want with integers. "Integers" itself, the math term, denotes the infinite set 1,2,3... and while computer arithmetic is necessary limited to a finite fragment, computer integer calculations should always give the same result that you would get using the unbounded mathematical integers. When that doesn't work, you should get an overflow exception, similar to running out of memory.

In Ada, I think the relevant exception is Constraint_Error, but I don't think Rust has a way to do that. By "that" I mean ordinary addition like "a+b" where and b are i32 variables, gets overflow checked without having to call checked_add(a,b) instead of a+b. Is that mistaken?

steveklabnik|1 year ago

> In Ada, I think the relevant exception is Constraint_Error, but I don't think Rust has a way to do that. By "that" I mean ordinary addition like "a+b" where and b are i32 variables, gets overflow checked without having to call checked_add(a,b) instead of a+b. Is that mistaken?

So, this answer to this is yes and no, in different senses.

So first of all, Constraint_Error is an exception, and Rust doesn't use exceptions for error handling like this. It does have panics, but a Rust-native API wouldn't use a panic in this situation. and so the type signature of checked_add looks like this, for i8:

  pub const fn checked_add(self, rhs: i8) -> Option<i8>
This returns an Option type, which you can than handle as you wish. So it's true, you invoke this like

  a.checked_add(b)
Now, there are two other common semantics for checked addition: saturating, and wrapping. They look like this:

  a.saturating_add(b)
  a.wrapping_add(b)
Okay. At this point we can actually get into the interesting part: yes, typing this is not as nice as a + b. However, for both saturating and wrapping addition, there are wrapper types:

  use std::num::Saturating;

  let max = Saturating(u32::MAX);
  let one = Saturating(1u32);

  max + one
to get a u32 back out, you use .0, since this is just a wrapper struct:

  (max + one).0
So! What about checked? Well... there isn't one. It appears that the reason why is that it was proposed, and then there wasn't a lot of enthusiasm, so it got closed. What's interesting is that Saturating was in that RFC as well, but I guess it made it in later.

There exist packages like https://crates.io/crates/checked so if you really want this anyway, you can still have it.