hrefspace

 找回密码
 立即注册
搜索
热搜: PHP PS 程序设计
查看: 1268|回复: 9

2个64bit的无符号整数相乘,C++如何实现最快?

[复制链接]

557

主题

557

帖子

1898

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1898
发表于 2023-9-26 21:25:28 | 显示全部楼层 |阅读模式
我想编写一个C++程序,

输入两个$64$bit的整数$a$和$b$,

然后计算$a$*$b$,结果为$128$bit的整数,

我希望用两个$64$bit的整数$h$和$l$表示这个$128$bit的整数,

其中$h$为前$64$个bit,$l$为后$64$个bit。

最后输出$h$和$l$。

例$1$:
===============
输入:
4294967297        4294967297
——————————
输出:
1        8589934593
===============

例$2$:
===============
输入:
18446744073709551615        18446744073709551615
——————————
输出:
18446744073709551614        1
===============

程序运行时间越短越好。

请问如何实现?
回复

使用道具 举报

948

主题

1162

帖子

3655

积分

超级版主

Rank: 8Rank: 8

积分
3655

论坛头条论坛元老谋士数据帝优秀版主超级版主见习版主论坛版主

发表于 2023-9-26 21:26:25 | 显示全部楼层
如果在64位OS中,直接乘即可;
如果在32位OS中,就比较麻烦了,要经历多次乘法,带位加法。
而乘法应尽量设计成并行的,指令集需用到SSE2,寄存器用到MM或XMM.
回复

使用道具 举报

0

主题

196

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-9-26 21:26:42 | 显示全部楼层
“如果在64位OS中,直接乘即可”

我知道直接乘可以得到低$64$位的$l$,高$64$位的$h$也可以直接乘得到吗?
回复

使用道具 举报

0

主题

189

帖子

163

积分

关内侯

Rank: 2

积分
163
发表于 2023-9-26 21:26:49 | 显示全部楼层
要用汇编,读取 RDX:RAX,其中 h <--RDX, l <-- RAX
回复

使用道具 举报

0

主题

166

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-9-26 21:27:01 | 显示全部楼层
在ubuntu系统,g++语言里面,

两个$64$bit的整数相乘,要得到一个$128$bit的整数,用什么指令?

网上只能找到两个$32$bit的整数相乘得到一个$64$bit的整数的指令。
回复

使用道具 举报

0

主题

184

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-9-26 21:27:19 | 显示全部楼层
c++里面好像不支持内嵌的64位指令
回复

使用道具 举报

0

主题

174

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-9-26 21:27:45 | 显示全部楼层
这个是不是与编译器是否支持相关?
好像记得是ICC支持的。
可惜现在我还没用过64位系统,没得试。
回复

使用道具 举报

0

主题

185

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2023-9-26 21:28:41 | 显示全部楼层
由于不知道$64$位直接乘如何实现,先暂时用多次$32$位乘法来实现。代码如下:
  1. void m64(unsigned __int64 a,unsigned __int64 b){        unsigned __int64 ah,al,bh,bl,m;        ah=unsigned int(a>>32);        al=unsigned int(a);        bh=unsigned int(b>>32);        bl=unsigned int(b);        l=ah*bl;        m=al*bh;        h=ah*bh+(l>>32)+(m>>32);        l<<=32;        m=(m<<32)+l;        if(m<l)h++;        l=al*bl+m;        if(l<m)h++;}
复制代码
其中,$l$和$h$是全局的无符号$64$位整数,是最终的结果。

不知道这段代码还有没有优化的余地。
回复

使用道具 举报

0

主题

182

帖子

67

积分

关内侯

Rank: 2

积分
67
发表于 2023-9-26 21:29:00 | 显示全部楼层
依葫芦画瓢,不知是否算更简洁些?
  1. void m64(unsigned __int64 a,unsigned __int64 b){        unsigned __int64 ah,al,bh,bl;        unsigned __int64 l,m,h;        ah=unsigned int(a>>32);        al=unsigned int(a);        bh=unsigned int(b>>32);        bl=unsigned int(b);        l=ah*bl;        m=al*bh+l;        h=((m<l)?(1ULL<<32):0)+ah*bh+(m>>32);        m<<=32;        l=al*bl+m;        if(l<m)++h;}
复制代码
回复

使用道具 举报

0

主题

166

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-9-26 21:29:08 | 显示全部楼层
特别注意:当 al*bh+ah*bl 溢出时,向 h 需加 2^32,而不是 1.
我是突然间发现并修正这个bug的。
(——再看楼主发给我的短消息,也指明了这点;可怜我刚才改了几遍,居然都仅+1)
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|小黑屋|hrefspace

GMT+8, 2024-11-25 13:21 , Processed in 0.067757 second(s), 22 queries .

Powered by hrefspace X3.4 Licensed

Copyright © 2022, hrefspace.

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