3

I want the following

(2u128.pow(x)) as u64

but such that it succeeds for x < 64 and fails for x >= 64.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Sarien
  • 6,647
  • 6
  • 35
  • 55

2 Answers2

4

As you correctly pointed out yourself, you should use TryFrom, but you should also make sure the exponentiation itself doesn't overflow, by using u128::checked_pow instead of u128::pow:

use std::convert::TryFrom;

let x = 129;
let y = 2u128.checked_pow(x).expect("Number too big for exponentiation");
let z = u64::try_from(y).expect("Number too big for cast");

(playground link)

Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • tbh I am kind of disappointed that pow() isn't checked. Where are the safe defaults, damnit? Thank, you! Good catch! – Sarien May 23 '19 at 18:55
  • 1
    @Sarien Rust aims to be a performant language, and tries not to force overhead on you if you don't want it. When running in debug mode, `pow()` will panic on overflow, but in release mode it is unchecked. This isn't considered "unsafe" in the Rust sense of the word, since it can't trigger undefined behaviour. If you want the check in release mode, you can still use `checked_pow()`. – Sven Marnach May 23 '19 at 19:25
  • 1
    Also, all the arithmetic operations can fail for the right pair of values. If they all returned a `Result`/`Option` rather than the behavior they have now, it would be sooooo painful to use. Consider that a simple `a + b*c` would become at least `(a + (b*c)?)?`. – mcarton May 23 '19 at 20:30
  • On the other hand, Rust also aims to be a safe language, so maybe it should either make me think about that case or just promote to BigInt if necessary. I understand the trade-off, though. – Sarien May 24 '19 at 06:06
  • 1
    Or you could use directly `2u64.checked_pow`, no need to go through a 128 bits value. – Jmb May 24 '19 at 06:14
0

Okay, found the answer, there is TryFrom.

use std::convert::TryFrom;

u64::try_from(2u128.pow(x)).expect("Number too big for cast.")

from here which I somehow missed with my first search.

Sarien
  • 6,647
  • 6
  • 35
  • 55
  • 2
    How about [even bigger `x`](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=3f571eba4117238a923039489c8b9964)? – mcarton May 23 '19 at 18:23