mathematica 发表于 2012-8-3 15:23:00

这个问题完全看不明白

G-Spider 发表于 2013-7-2 22:13:46

KeyTo9_Fans 发表于 2012-7-19 21:13
在ubuntu系统,g++语言里面,

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


x64 指令:
IMUL r/m64   
(表示 RDX:RAX= RAX*r/m64)
对应两个无符号64位乘,得到128位的结果,高64位进rdx(不够的填0),低64位进rax中。

KeyTo9_Fans 发表于 2019-4-28 12:20:59

直接用UnsignedMultiply128函数似乎就可以了。

参考文献:
https://docs.microsoft.com/zh-cn/windows/desktop/api/winnt/nf-winnt-unsignedmultiply128

但以下这段代码:

#include<Windows.h>
#include<winnt.h>
#include<cstdio>
unsigned __int64 a, b, c, d;
int main()
{
        scanf_s("%I64u%I64u", &a, &b);
        d = UnsignedMultiply128(a, b, &c);
        return 0;
}

编译出现如下错误:

m128.cpp(8): error C3861: “UnsignedMultiply128”:找不到标识符

初步猜测是我的电脑缺少相应的硬件,比如:$64$位处理器。

mathe 发表于 2019-4-28 14:40:44

你的代码是编译成32位代码还是64位代码?
如果32位代码自然不支持,但是如果是64位代码,应该是支持的,64位乘法的支持不需要很新的硬件
比如VS中默认工程有可能是WIN32,就代表32位代码,要改成WIN64的才行。
当然操作系统也要求是64位的,但是我相信现在一般人都应该已经用64位操作系统了

https://stackoverflow.com/questions/13132635/umul128-identifier-not-found

另外AMD 在2003年就推出64位处理器Opteron了,而Intel紧跟者在2004年也推出了64位的Pentium 4。现在想找到不支持64位的PC机处理器还是很困难的。
另外,如果你使用32位代码模式,在Windows上,一个进程用户态内存是无法超过2G的,但是64位就没有这个限制了。

.·.·. 发表于 2019-4-28 15:26:52

本帖最后由 .·.·. 于 2019-4-28 15:32 编辑

KeyTo9_Fans 发表于 2012-7-23 20:50
由于不知道$64$位直接乘如何实现,先暂时用多次$32$位乘法来实现。代码如下:其中,$l$和$h$是全局的无符号 ...

unsigned long long a,d;
...
        asm ("mul %%rdx"
                : "+a" (a) ,"+d"(d));
...
这个函数把a*d储存到a跟d中
a是低64位,d是高64位
gcc可以编译通过
记得输出的时候用%llu,否则显示会出问题

dlpg070 发表于 2019-4-28 20:21:10

c++ proj的设置应为x64,不是x86
代码正确
------------
1个例子:
a=123456789012
b=123456789012
算得:
c=826             a*b的高64bit
d=45681482693943a*b的低64bit

a*b=15241578753153483936144 10进制数值
c,d 只是a*b的高64bit ,低64bit,不能直接得到10进制数值

.·.·. 发表于 2019-4-29 13:58:51

dlpg070 发表于 2019-4-28 20:21
c++ proj的设置应为x64,不是x86
代码正确
------------


话说……gcc完全跑不动这个栗子
话说,为啥这么多人用VS写密集计算的代码呢?
我看到的几乎所有library都是(在windows环境下)要用gcc/cygwin/msys2之类东西编译的

B:\>g++ B:\m64.cpp -o m64.exe
B:\m64.cpp: In function 'int main()':
B:\m64.cpp:7:13: error: 'scanf_s' was not declared in this scope
             scanf_s("%I64u%I64u", &a, &b);
             ^~~~~~~
B:\m64.cpp:7:13: note: suggested alternative: 'sscanf_s'
             scanf_s("%I64u%I64u", &a, &b);
             ^~~~~~~
             sscanf_s

风云剑 发表于 2019-4-29 16:36:33

为啥这么多人用VS写密集计算的代码呢
大概是因为用windows的人多吧,而且VS编译出来的程序优化也不错。

wayne 发表于 2019-4-30 21:08:26

gcc其实是支持128bit整数的:https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html
#include <iostream>

int main()
{
//    typedef unsigned int uint128_t __attribute__((mode(TI)));
    typedef unsigned __int128 uint128_t;

   uint64_t x = 0xABCDEABCDEABCDEF;
   uint64_t y = 0xABABABABABABABAB;

   uint128_t result = (uint128_t)x * y;
   uint64_t low = result;
   uint64_t high = result >> 64;

   printf("%016llX * %016llX = %016llX%016llX\n", x, y,high,low);

    return 0;
}


运行得到:
ABCDEABCDEABCDEF * ABABABABABABABAB = 7335C18DB67335C3F633A7DBB2F633A5
对于这个结果,肉眼凡胎看起来有些茫然,那就 用Mathematica验证一下:
In:= BaseForm*FromDigits["ABABABABABABABAB",16],16]
Out//BaseForm= Subscript
哈哈哈,竟然是 一致的!

灵树 发表于 2020-5-13 09:50:54

大整数相乘就是一个移位和进位的问题,处理好这两个问题很容易解决。同样可以扩展到任意大数的计算上。
页: 1 [2] 3
查看完整版本: 2个64bit的无符号整数相乘,C++如何实现最快?