- 注册时间
- 2010-2-12
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 1214
- 在线时间
- 小时
|
发表于 2017-2-1 11:35:35
|
显示全部楼层
受到各位高手的刺激,加上本人对大数运算的爱好,经过深入的思考,不断的摸索,终于得到了我自己比较满意的结果。
由于站长已经把路堵死了,本人只有把站长的题目改动一下:
只用4次32位乘法,求 uint64_t 对 10^9 的余数及商。
(这里,我就不管LED灯的问题了)
程序中用到了管理员 liangbch 在 http://bbs.emath.ac.cn/thread-9245-1-1.html 中提供的“规约”技术。
我用的是vc++2008, 在debug环境下测试通过。
以下是程序的源码
- #include <stdio.h>
- #include <windows.h>
- _declspec(naked)
- int div_mod(UINT32 *dst,UINT32 *scr)
- {
- _asm
- {
- push esi
- push edi
- push ebx
- push ebp
-
-
- mov esi,dword ptr[esp+08h+16]
- mov ebp,dword ptr[esp+04h+16]
-
- mov eax,1152921504///-----这是10^(-9)的高32位
- mul dword ptr[esi]//64位的低位 乘 10^(-9)的高32位
-
- mov edi,edx //乘积的结果,暂时保存在 edi ebx 中。
- mov ebx,eax
- mov eax,2606387915 //-------这是10^(-9)的低32位
- mul dword ptr[esi+4]// 64位的高位 乘 10^(-9)的低32位
-
- add ebx,eax
- adc edi,edx //edi 将作为进位,edi ebx 存储结果
-
- mov eax,1152921504//-----这是10^(-9)的高32位
- mul dword ptr[esi+4]// 64位的高位 乘 10^(-9)的高32位
-
- add eax,edi //把edi加进来,丢弃ebx中的低32位
- adc edx,0 //eax edx 中包含了 原始64位/10^9的商,其中 edx 存储高32位,eax 存储低32位。
-
- shrd eax,edx,28//整体右移28位,右移方向 edx->eax->28,右移后 eax 中是商的低32位
-
- //shr edx,28 //得到商的高4位
- mov ecx,eax //保留商的低32位
- //mov ebx,edx //保留商的高32位
- mov eax,1000000000
- mul ecx //ecx 商的低32位
- //这一步执行后,我们将丢弃edx中的数,只取 eax 中的值。
-
- mov esi,dword ptr[esp+08h+16]
- mov edi,dword ptr[esi] //edi 原始64位数的低32位,
- sub edi,eax // a64 mov 10^9 的结果,保存在 edi 中
- //以下语句对 edi 中的余数和 ebx ecx 中的商进行调整,这个方法由管理员 liangbch 在http://bbs.emath.ac.cn/thread-9245-1-1.html 中提供。
- mov esi,1000000000
- mov edx,0xffffffff
- xor eax,eax
- cmp edi,esi
- SETB eax
- add edx,eax
- mov eax,edx//传送进位
- and edx,esi
- sub edi,edx
- mov dword ptr[ebp],edi //得到 a64 mod 10^9 (余数)的准确值,返回主函数
- //neg eax
- //add ecx,eax
- //adc ebx,0 // 得到 a64/10^9 (商)的准确值,其中 ebx中存储商的高32位,ecx中存储商的低32位
- //如果需要 a64/10^9 (商) 的值,把第 38、40、65、66、67 行的注释取消即可。
- pop ebp
- pop ebx
- pop edi
- pop esi
-
- ret
- }
- }
- int main()
- {
- UINT64 a64;
- UINT32 scr[2],dst[1];
- a64=30789000000000;
-
- scr[1]=(UINT64)a64/4294967296;
- scr[0]=(UINT64)a64%4294967296;
-
- div_mod(dst,scr);/// dst[] 返回的是 a64 mod 10^9 (余数)。
- /// 若有需要,可以同时返回 a64/10^9 (商)。
- printf("dst=%d\n",dst[0]);
-
- system( "pause" );
- return 0;
- }
复制代码 |
|