前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust-盘一下数字相关的函数(二)

Rust-盘一下数字相关的函数(二)

作者头像
江湖安得便相忘
发布2019-10-14 15:42:24
1.4K0
发布2019-10-14 15:42:24
举报
上期内容:Rust-盘一下数字相关的

上一次盘的是有符号整数的相关函数实现,包括一些位运算、几个科学计算方法等等,这回盘一下计算检测溢出的几个方法,以及其中的区别。

以下均处于int_impl宏内,其中部分方法与uint_impl实现有区别。

overflowing_* 系列:

const fn overflowing_add(self, rhs: Self) -> (Self, bool) 加法,正常二进制加法运算,如果存在溢出返回的元组中的bool为true;两个加数与和的类型必须相同。

代码语言:javascript
复制
let num:i8 = std::i8::MAX;
println!("{:?}", a.overflowing_add(2));
-----
(-127, true)

const fn overflowing_sub(self, rhs: Self) -> (Self, bool) 带溢出检测的减法运算。

const fn overflowing_mul(self, rhs: Self) -> (Self, bool) 带溢出检测的乘法。

const fn overflowing_div(self, rhs: Self) -> (Self, bool) 带溢出检测的除法,rhs是除数,self是被除数。当rhs为0时程序会panic。仅当被除数是有符号类型内最小值并且除数rhs是-1时会发生溢出,其余均不会溢出。

代码语言:javascript
复制
//函数原型
fn overflowing_div(self, rhs: Self) -> (Self, bool) {
    if self == Self::min_value() && rhs == -1 {
        (self, true)
    } else {
        (self / rhs, false)
    }
}

fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) 欧几里得除法,同样在被除数是最小值且除数为-1时有溢出。

fn overflowing_rem(self, rhs: Self) -> (Self, bool) 取余,溢出情况与除法相同。

fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) 欧几里得取余,溢出情况与除法相同。

const fn overflowing_neg(self) -> (Self, bool) 变换正负号,当self是类型内最小值时会发生溢出。

代码语言:javascript
复制
println!("{:?}", (-128_i8).overflowing_neg());
-----
(-128, true)

const fn overflowing_shl(self, rhs: u32) -> (Self, bool) 带溢出的左移rhs位。当移位量大于类型字节数-1时发生溢出,溢出后则重新再次左移。所以移位rhs次与 rhs % 8 次结果是相同的。

代码语言:javascript
复制
(0x50_i8).overflowing_shl(7);
(0x50_i8).overflowing_shl(9);
-----
(0x0, false)
(0xA0, true)

const fn overflowing_shr(self, rhs: u32) -> (Self, bool) 带溢出的右移。

fn overflowing_abs(self) -> (Self, bool) 带溢出的绝对值,负数时,可参考overflowing_neg()方法。

fn overflowing_pow(self, mut exp: u32) -> (Self, bool) 带溢出的乘方。其溢出实现如下,在计算过程中发生溢出时,会使用溢出计算得到的值继续计算。

代码语言:javascript
复制
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
    let mut base = self;
    let mut acc: Self = 1;
    let mut overflown = false;
    // Scratch space for storing results of overflowing_mul.
    let mut r;

    while exp > 1 {
        if (exp & 1) == 1 {
            r = acc.overflowing_mul(base);
            acc = r.0;
            overflown |= r.1;
        }
        exp /= 2;
        r = base.overflowing_mul(base);
        base = r.0;
        overflown |= r.1;
    }

    // Deal with the final bit of the exponent separately, since
    // squaring the base afterwards is not necessary and may cause a
    // needless overflow.
    if exp == 1 {
        r = acc.overflowing_mul(base);
        acc = r.0;
        overflown |= r.1;
    }

    (acc, overflown)
}

checked_* 系列:

checked_* 系列其后缀名称与overflowing_* 系列一致,但返回值是Option类型,溢出会返回None。

wrapping_* 系列:

wrapping_* 系列方法但后缀与overflowing_* 系列一致,返回值为同类型计算结果,与overflowing_* 计算结果相同,大部分溢出使用截断策略。

saturating_* 系列:

方法较少,溢出时会返回边界值。

const fn saturating_add(self, rhs: Self) -> Self 加法。

const fn saturating_sub(self, rhs: Self) -> Self 减法。

fn saturating_neg(self) -> Self 变换正负号。

fn saturating_abs(self) -> Self 绝对值。

fn saturating_mul(self, rhs: Self) -> Self 乘法。其内部使用checked_mul实现。

代码语言:javascript
复制
pub fn saturating_mul(self, rhs: Self) -> Self {
    self.checked_mul(rhs).unwrap_or_else(|| {
        if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) {
            Self::max_value()
        } else {
            Self::min_value()
        }
    })
}

fn saturating_pow(self, exp: u32) -> Self 幂运算,内部使用checked_pow实现。

代码语言:javascript
复制
pub fn saturating_pow(self, exp: u32) -> Self {
    match self.checked_pow(exp) {
        Some(x) => x,
        None if self < 0 && exp % 2 == 1 => Self::min_value(),
        None => Self::max_value(),
    }
}

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可回收BUG 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档