判断两数相加、相乘是否溢出

目的

  • 判断两个同类型的值相加是否溢出。
  • 判断两个同类型的值相乘是否溢出。

前提

推导 1

有 x + y = z,若不溢出,输出 z;若溢出,输出 r。

w = 8,当 0 ≦ x,y ≦ 127 时,0 ≦ x + y ≦ 254,即 z ∈ [0, 254]。

当 z ∈ [128, 254] 时,溢出,输出 r 为 z - 256。

例:127 + 3 = 130,输出 130 - 256 = -126。

byte b = 127;
b += 3;
System.out.println(b);// -126

猜想,是否能用 r - y != x,判断两数相加溢出?

public static boolean isOK_Add(int x, int y) {
    int r = x + y;
    return r - y == x;
}

目标:

  • 如果 z 溢出,证明 r - y != x,即证明此方法返回 false。

没有溢出时,r = z。要求:此方法返回 true

  • x + y = r。
  • r - y = x 为 true,此方法返回 true。

由于以 8 位为例,使用 byte 验证。但 Java 中 byte 参与运算时会自动提升为 int 类型,int 类型的取值范围太大,不好验证,所以需要强转。

byte x = 24;
byte y = 55;
byte r = (byte)(x + y);// 79
// 79 - 55 == 24
System.out.println(r - y == x);// true

溢出时 r = z - 256。要求:此方法返回 false

  • x + y = r + 256。
  • r - y = x - 256。
  • x ∈ [0, 127],x - 256 ∈ [-256, -129]。

x - 256 负溢出,r - y 的输出结果为 (x - 256) + 256 = x。此方法返回 true。

推导失败!猜想错误!

byte x = 124;
byte y = 55;
// 179 正溢出,结果为 179 - 256 = -77
byte r = (byte)(x + y);// -77
// -77 - 55 = -132,负溢出,结果为 -132 + 256 = 124
System.out.println((byte)(r - y) == x);// true

推导 2

0 ≦ x,y ≦ 127 时,z ∈ [0, 254]。

  • 当 z ∈ [128, 254] 时,溢出,输出 r 为 z - 256。

  • 此时 r ∈ [-128, -2],为负数,小于 x 且小于 y。

  • 所以,如果 r < x,则正溢出。

int r = x + y;
if (x >= 0 && y >= 0) {
    return r >= x;
}

-128 ≦ x,y ≦ -1 时,z ∈ [-256, -2]。

  • 当 z ∈ [-256, -129] 时,溢出,输出 r 为 z + 256。
  • 此时 r ∈ [0, 127],为非负数,大于 x 且大于 y。
  • 所以,如果 r > x,则负溢出。
if (x < 0 && y < 0) {
    return r <= x;
}

-128 ≦ x ≦ -1,0 ≦ y ≦ 127 时,z ∈ [-128, 126],没有溢出,返回 true。

// 返回 true:没有溢出
// 返回 false:溢出
public static boolean isOK_Add(int x, int y) {
    int r = x + y;
    if (x >= 0 && y >= 0) {
        return r >= x;
    }
    if (x < 0 && y < 0) {
        return r <= x;
    }
    return true;
}

推导 3

有 x * y = z,若不溢出,输出 z;若溢出,输出 r。

两非负数相乘

w = 8,当 0 ≦ x,y ≦ 127 时,0 ≦ x * y ≦ 16129,即 z ∈ [0, 16129]。

当 z ∈ [128, 16129] 时,正溢出。

  • 若 z % 256 ∈ [0, 127],则 r = z % 256。
  • 若 z % 256 ∈ [128, 255],则 r = z % 256 - 256。

猜想,是否能用 r / y != x,判断两非负数相乘溢出?

前提:y != 0 且 x != 0,这些值要提前处理,避免除零异常。

public static boolean isOK_Multiply(int x, int y) {
    if (x == 0 || y == 0 
        || x == 1 || y == 1) {
        return true;
    }
    int r = x * y;
    return r / y == x;
}

目标:

  • 如果 z 溢出,证明 r / y != z / y,即证明此方法返回 false。

没有溢出时,r = z。要求:此方法返回 true

  • x * y = r。
  • r / y = x 为 true,此方法返回 true。

溢出时 r = z % 256 或 z % 256 - 256。要求:此方法返回 false

byte b = 50;
b *= 30;
// 1500 正溢出,1500 % 256 = 220,输出 220 - 256 = -36 
System.out.println(b);// -36

当 z % 256 ∈ [0, 127],r = z % 256 时:

  • r / y = z % 256 / y

  • 比较 z % 256 / yz / y

  • 当 z ∈ [0, 255] 时,两式子相等,方法就会返回 true。

  • 当 z ≧ 256,两式子不相等,方法就会返回 false。

现有条件:

  • z 溢出,所以 z > 127。

  • z % 256 ∈ [0, 127],则有 z = 256 * n + k,n 为非负整数,k ∈ [0, 127]。

    当 n = 0 时,z = k,z ∈ [0, 127]。

    当 n > 0 时,z ≧ 256。

  • 两个条件结合,z ≧ 256,所以方法返回 false。

当 z % 256 ∈ [128, 255],r = z % 256 - 256 时:

  • r / y = (z % 256 - 256) / y
  • 比较 (z % 256 - 256) / yz / y
  • 当 z % 256 - 256 = z 即 z % 256 = z + 256 时,两个式子相等。
  • 然而 z + 256 ≧ 256,z % 256 ∈ [0, 255],不可能存在 z 使这两个式子相等,方法返回 false。

两负数相乘

当 -128 ≦ x,y ≦ -1 时,1 ≦ x * y ≦ 16384,即 z ∈ [1, 16384]。

当 z ∈ [128, 16384] 时,溢出。

证明过程同上。

一正一负

当 -128 ≦ x ≦ -1,0 ≦ y ≦ 127 时,z ∈ [-16256, 0]。

当 z ∈ [-16256, -129] 时,负溢出。

  • 若 z % 256 = 0,则 r = 0。

  • 若 z % 256 ∈ [-128, -1],则 r = z % 256。

  • 若 z % 256 ∈ [-255, -129],则 r = z % 256 + 256。

溢出时,当 z % 256 = 0,r = 0 时:要求:此方法返回 false

  • r / y = 0。
  • 比较 0 与 z/y。
  • 当 z = 0 时,两式子相等,此方法返回 true。
  • 然而负溢出,z != 0,此方法返回 false。

溢出时,当 z % 256 ∈ [-128, -1],r = z % 256 时:要求:此方法返回 false

  • r / y = z % 256 / y

  • 比较 z % 256 / yz / y

  • 当 z ∈ [-255, 0] 时,两式子相等,方法就会返回 true。

  • 当 z < -256 时,两式子不相等,方法就会返回 false。

现有条件:

  • z 负溢出,z < -128。

  • z % 256 ∈ [-128, -1],则有 z = 256 * n + k,n 为非正整数,k ∈ [-128, -1]。

    当 n = 0 时,z = k,z ∈ [-128, -1]。

    当 n < 0 时,z < -256。

  • 两个条件结合,z < -256,所以方法返回 false。

溢出时,当 z % 256 ∈ [-255, -129],r = z % 256 + 256 时:要求:此方法返回 false

  • r / y = (z % 256 + 256) / y。
  • 比较 (z % 256 + 256) / yz / y
  • 当 z % 256 + 256 = z 即 z % 256 = z - 256 时,两个式子相等。
  • 然而 z - 256 ≦ -256,z % 256 ∈ [-255, 0],不可能存在 z 使这两个式子相等,方法返回 false。

证毕,此方法有效。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值