找回密码
 立即注册
查看: 360|回复: 11

两个32位数相乘得到的结果最高64位,溢出怎么办?

[复制链接]
已绑定手机

1

主题

8

回帖

339

积分

中级会员

积分
339
发表于 2026-10-22 10:04:04 | 显示全部楼层 |阅读模式
请教一下各位大佬,两个32位数相乘得到的结果最高64位,而结果的寄存器也是32位的,溢出怎么办?怎么判断得到的结果是不是正确的?
回复

使用道具 举报 送花

已绑定手机

74

主题

1019

回帖

3777

积分

论坛元老

初出茅庐&无甚本事

积分
3777
发表于 2026-10-22 11:34:37 | 显示全部楼层
32位的结果寄存器溢出,则结果没办法直接用,看看有没有现成的库,或者自己实现基本算法。
能不能检查溢出标志位,溢出的结果不能当正确的
比较可靠的参考以官方手册为准


用16位乘法
得到32位数值
移位拼凑64位结果

设 a = ah:al,b = bh:bl(各16位)
y0 = al*bl
y1 = al*bh
y2 = ah*bl
y3 = ah*bh
结果64位 =  y =y3<<32 + (y2+y1)<<16 + y0


偶尔看看玩玩
回复

使用道具 举报 送花

54

主题

1481

回帖

3727

积分

超级版主

积分
3727
发表于 2026-10-22 11:39:24 | 显示全部楼层
STC官网:https://www.stcai.com/
QQ:2593903262
微信号:18106296598
回复

使用道具 举报 送花

已绑定手机

1

主题

8

回帖

339

积分

中级会员

积分
339
 楼主| 发表于 2026-10-22 15:25:49 | 显示全部楼层
狂热*** 发表于 2026-10-22 11:34
32位的结果寄存器溢出,则结果没办法直接用,看看有没有现成的库,或者自己实现基本算法。
能不能检查溢出 ...

好的,谢谢,如果移位拼凑,这个和16位乘法器也差不多。感觉这个32位的比16位的提升的不多。
回复

使用道具 举报 送花

已绑定手机

1

主题

8

回帖

339

积分

中级会员

积分
339
 楼主| 发表于 2026-10-22 15:27:25 | 显示全部楼层

我在发帖前也问了一下助手,它的解释也是差不多这样的。
回复

使用道具 举报 送花

已绑定手机

24

主题

701

回帖

2731

积分

金牌会员

积分
2731
发表于 2026-10-22 15:39:36 | 显示全部楼层
如果可能溢出,该使用浮点数了,8位机一般不支持64位数
回复

使用道具 举报 送花

24

主题

546

回帖

2621

积分

荣誉版主

积分
2621
发表于 2026-10-22 20:31:03 | 显示全部楼层
STC32G144K246的DSP有32位乘除运算A * B / C,可惜是有符号数运算。
回复

使用道具 举报 送花

24

主题

546

回帖

2621

积分

荣誉版主

积分
2621
发表于 2026-10-22 20:50:00 | 显示全部楼层
十多年前,曾应客户要求,做过32位的电子齿轮比算法,不依赖乘除运算,且运行速度超快。
回复

使用道具 举报 送花

已绑定手机

1

主题

8

回帖

339

积分

中级会员

积分
339
 楼主| 发表于 2026-10-23 15:12:17 | 显示全部楼层
再请教一下,STC8H支持MDU16的系列,加了STC8_MDU16.LIB后,做两个16位乘法运算C语言该用哪个表达:
u16 a,b;
u32 c;
表达式1:c = a*b;
表达式2:c = (u32)a*b;
表达式1在没有库的时候应该会得出16位的结果,溢出部分就丢掉了吧,加了库会编译成32位吗?
表达式2在没有库的时候应该会得出正确的32位的结果,但是加了库会不会被编译器理解成32位相乘而不用库文件编译?

点评

表达式3:c = (u32) a * (u32) b;  详情 回复 发表于 2026-10-24 13:45
回复

使用道具 举报 送花

79

主题

1108

回帖

4966

积分

荣誉版主

积分
4966
发表于 2026-10-24 13:43:11 | 显示全部楼层
(1)你有两个问题,我分别回答。但首先假定你使用的是C51/C251编译器,它们没有64位的整数类型和运算。

(2)第一个问题,如何判断得到的结果是不是正确的,也就是判断32位的两个数a和b相乘的结果是否超过32位产生溢出。
判断溢出的方法,首先判断a和b是否有一个或者两个为0,为0就肯定结果为0。然后用除法:
A)无符号整数乘法

bool mul_overflow_u32(uint32_t a, uint32_t b) {
    if (a == 0 || b == 0) return false;
    return a > UINT32_MAX / b;   // 用除法避免乘法溢出
}

其中UINT32_MAX是无符号32位整数最大值,UINT32_MAX=0xFFFFFFFF;

B)有符号整数乘法

bool mul_overflow_i32(int32_t a, int32_t b) {
    if (a > 0) {
        if (b > 0) {
            return a > INT32_MAX / b;
        } else {
            return b < INT32_MIN / a;
        }
    } else {
        if (b > 0) {
            return a < INT32_MIN / b;
        } else {
            // 两个负数:a*b 为正,需 a < INT32_MAX / b(注意 b<0)
            return a != 0 && b < INT32_MAX / a;
        }
    }
}

其中32位有符号整数的最大值和最小值为INT32_MAX=0x7FFFFFFF,INT32_MIN=0x80000000;

(3)第二个问题,溢出怎么办?当然将32位乘32位的结果用64位来表达。解决的方法如下:
A)用C语言,那么请用STC IDE —— 面向STC32系列及AI8051U的C语言编译器,它有64位的整数类型和运算
B)用硬件汇编语言,可以选用具有DSP32的STC单片机:
DSP32_乘法.jpg
C)用软件汇编语言,可以请教STC AI助手



回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-8 02:40 , Processed in 0.083575 second(s), 86 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表