如何在无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
相关产品推荐
相关产品推荐

