oracle计算时sum溢出_检测uint64_t整数溢出与C的乘法

当使用int64_t或uint64_t操作数的乘法运算在C中溢出时,是否有任何高效便捷的方式?

例如,为了添加uint64_t,我可以做:

if (UINT64_MAX - a < b) overflow_detected();

else sum = a + b;

但是我不能得到一个类似的简单的乘法表达式.

所有这一切发生在我身上,将操作数分解成高低的uint32_t部分,并执行这些部分的乘法,同时检查溢出,真的很丑陋,也可能是低效的.

更新1:添加了几个实现几种方法的基准代码

更新2:添加了Jens Gustedt方法

基准计划:

#include

#include

#include

#define N 100000000

int d = 2;

#define POW_2_64 ((double)(1 << 31) * (double)(1 << 31) * 4)

#define calc_b (a + c)

// #define calc_b (a + d)

int main(int argc,char *argv[]) {

uint64_t a;

uint64_t c = 0;

int o = 0;

int opt;

if (argc != 2) exit(1);

opt = atoi(argv[1]);

switch (opt) {

case 1: /* faked check,just for timing */

for (a = 0; a < N; a++) {

uint64_t b = a + c;

if (c > a) o++;

c += b * a;

}

break;

case 2: /* using division */

for (a = 0; a < N; a++) {

uint64_t b = a + c;

if (b && (a > UINT64_MAX / b)) o++;

c += b * a;

}

break;

case 3: /* using floating point,unreliable */

for (a = 0; a < N; a++) {

uint64_t b = a + c;

if ((double)UINT64_MAX < (double)a * (double)b) o++;

c += b * a;

}

break;

case 4: /* using floating point and division for difficult cases */

for (a = 0; a < N; a++) {

uint64_t b = a + c;

double m = (double)a * (double)b;

if ( ((double)(~(uint64_t)(0xffffffff)) < m ) &&

( (POW_2_64 < m) ||

( b &&

(a > UINT64_MAX / b) ) ) ) o++;

c += b * a;

}

break;

case 5: /* Jens Gustedt method */

for (a = 0; a < N; a++) {

uint64_t b = a + c;

uint64_t a1,b1;

if (a > b) { a1 = a; b1 = b; }

else { a1 = b; b1 = a; }

if (b1 > 0xffffffff) o++;

else {

uint64_t a1l = (a1 & 0xffffffff) * b1;

uint64_t a1h = (a1 >> 32) * b1 + (a1l >> 32);

if (a1h >> 32) o++;

}

c += b1 * a1;

}

break;

default:

exit(2);

}

printf("c: %lu,o: %u\n",c,o);

}

到目前为止,使用浮点过滤大多数情况的情况4是最快的,当假定溢出是非常不寻常的,至少在我的电脑上,它比无人操作的情况下慢两倍.

情况5比4慢了30%,但它总是执行相同的,没有任何特殊的案例编号需要较慢的处理,就像4发生的那样.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值