文章内容:
/*
文件名称:DIV64_32.C
制作日期: 2008.8.15 REV2
作者: zzwj5120
Email: wjandcf@gmail.com
zzwj5120@sina.com
源程序: 64位无符号二进制整数除法原理(C语言描述)
函数功能: 64位无符号二进制整数除以32位无符号二进制整数
0000 0001 0000 0000
-----------------------------------------
0000 0000 ffff ffff ) 0000 0000 0000 0000 ffff ffff 0000 0000
0000 0000 ffff ffff
-----------------------------------------
0
*/
typedef signed short int16; /* defined for nsigned 16-bits integer variable 有符号16位整型变量 */
typedef signed int int32; /* defined for nsigned 32-bits integer variable 有符号32位整型变量 */
typedef long long int64; /* defined for nsigned 64-bits integer variable 有符号64位整型变量 */
typedef unsigned short uint16; /* defined for unsigned 16-bits integer variable 无符号16位整型变量 */
typedef unsigned int uint32; /* defined for unsigned 32-bits integer variable 无符号32位整型变量 */
typedef unsigned long long uint64; /* defined for unsigned 64-bits integer variable 无符号64位整型变量 */
/*
入口参数: ll, 被除数 bb, 除数 addr3 商指针 addr4, 余数指针
返回参数: 返回1表示除数为0, 返回0表示正常
*/
uint16 uint64_div_uint32(uint64 ll, uint32 bb, uint64 * addr3, uint32 * addr4){
union {
uint64 un[2]; //64位被除数扩展为128位,高64位为被除数左移64次而设
struct{
uint32 l0; //0
uint32 h0; //1
uint32 l1; //2
uint32 h1; //3
}st;
}aa;
uint64 cc; //64位商
register uint32 i;
if(bb == 0)return 1; //除数为0返回1
if(ll < bb){
*addr3 = 0; //商
*addr4 = ll; //余数
return 0; //被除数小于除数,商为0,余数即被除数
}
aa.un[0] = ll; //被除数 64bit
aa.un[1] = 0; //扩展到128bit
cc = 0; //商 64bit 清0
i = 0;
//第一步优化, 被除数为32位, 直接更改左移循环次数
if(aa.st.h0 == 0){
aa.st.h0 = aa.st.l0;
aa.st.l0 = 0;
i = 32;
}
//第二步优化, 左移直到被除数首位为1
for(;i<64; ++i){
if((aa.st.h0&0x80000000)==0x80000000)break;
else aa.un[0] = aa.un[0] << 1;
}
//被除数左移, 和除数比较, 获取商位和余数
for (; i<64; ++i){
aa.un[1] = (aa.un[1] << 1) + (aa.un[0] >> 63);
aa.un[0] = aa.un[0] << 1; //被除数左移1位
cc = cc << 1 ; //商左移1位
if(aa.un[1] >= bb){ //如果除数为32位,只可以用33位和除数比较
aa.un[1] = aa.un[1]- bb; //32位被除数可能比除数小,但有进位33
++cc;
}
}
*addr3 = cc; //商
*addr4 = aa.st.l1; //余数
return 0;
}
/*
一个不懂汇编的程序员,可能是一个合格的程序员但一定不是一个完美的程序员。
进一步的优化, 是根据不同处理器, 将C函数转为具体汇编指令。
*/