You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无64位整数的GLSL中检测int乘法溢出?

在GLSL 3.0(WebGL 2环境)中检测32位整数乘法溢出

背景

在C/C++中,我们可以通过64位整数类型规避32位int乘法的提前溢出,进而检测溢出情况,示例代码如下(修正了原代码的潜在问题):

int[] multiply(int a, int b){
  long long r = (long long)a * b; // 先转64位再相乘,避免int范围溢出
  int result = (int)r;
  int overflow = r >> 32; // 高位非零则说明溢出
  return {result, overflow};
}

问题

GLSL 3.0(基于WebGL 2运行在浏览器环境)不支持64位整数类型,如何实现等价的32位int乘法溢出检测?


可行方案

方案1:除法反向验证

核心思路是利用乘法与除法的逆运算关系:若a * b未溢出,则(a * b) / b == a(需排除除数为0的情况),同时单独处理INT_MIN * -1这类极端溢出场景(因为INT_MIN是32位有符号整数的最小值,乘以-1会超出范围)。

GLSL实现代码:

const int INT_MAX = 2147483647;
const int INT_MIN = -2147483648;

// 计算a*b,返回结果和溢出标记
void multiplyAndCheck(int a, int b, out int result, out bool overflow) {
    result = a * b;
    overflow = false;

    if (b == 0) {
        return;
    }

    // 处理唯一的正数溢出场景:INT_MIN * -1
    if ((a == INT_MIN && b == -1) || (b == INT_MIN && a == -1)) {
        overflow = true;
        return;
    }

    // 反向验证:若除法结果不等于原数,则说明溢出
    overflow = ((result / b) != a);
}

方案2:极值范围判断

通过比较操作数与INT_MAX/INT_MIN的除法结果,提前预判是否会溢出:

  • 当a和b同号时,若a > INT_MAX / b(正数)或a < INT_MAX / b(负数,因为两负数相乘得正数,上限是INT_MAX),则溢出
  • 当a和b异号时,若a < INT_MIN / b或b < INT_MIN / a,则溢出

GLSL实现代码:

const int INT_MAX = 2147483647;
const int INT_MIN = -2147483648;

void multiplyAndCheck(int a, int b, out int result, out bool overflow) {
    result = a * b;
    overflow = false;

    if (b == 0) {
        return;
    }

    // 同号相乘场景
    if ((a > 0 && b > 0)) {
        overflow = (a > INT_MAX / b);
    } else if ((a < 0 && b < 0)) {
        if (b == -1) {
            overflow = (a == INT_MIN);
        } else {
            overflow = (a < INT_MAX / b);
        }
    } 
    // 异号相乘场景
    else if (a < 0) {
        overflow = (a < INT_MIN / b);
    } else {
        overflow = (b < INT_MIN / a);
    }
}

内容的提问来源于stack exchange,提问作者BlobKat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:05:48