原创
快速实现乘、除运算的算法(适用于单片机等计算能力有限的系统)。 ...
从学习单片机以来,就一直被强调,单片机计算能力有限,进行数据乘、除操作十分耗费资源。
本人最近在研究51操作系统,接触底层比较多,昨晚突发奇想,想要设计基于位操作的乘、除算法。经过仔细思考和规律分析,摸索出一个可行的算法,如果担心、不确定MCU的效率,可供使用。话不多说,直接上代码:
//------------------------------------------------------------------
// 功能: 使用位操作实现数据的乘法运算
// 输入: x-乘数
// y-被乘数
// 输出: 无(使用VC++编写,结果会直接打印在屏幕上)
//-----------------------------------------------------------------
void multiple(int x, int y)
{
int operate = x, operated = y, result = 0;
char i = 0;
do
{
if(operate&0x01)
{
result += (operated<
}
++i;
}while(operate >>= 1);
printf("%d * %d = %d\r\n", x, y, res);
}
//------------------------------------------------------------------
// 功能: 使用位操作实现数据的除法运算
// 输入: x-除数
// y-被除数
// 输出: 无(使用VC++编写,结果会直接打印在屏幕上)
//-----------------------------------------------------------------
int divide(int x, int y)
{
int operate = x, operated = y, result = 0;
char i = 0;
//找出除数的最高位,确认操作次数。结果(operate < (0x01<
while(operate>>i) i++;
for(i; i >= 0; i--)
{
if(operate >= (operated<
{
/*减掉接近operate的operated最大倍数,60/3,第一次最接近60的3的最大倍数为16,60减去3*16后为12,此时最接近12的3的最大倍数为4。减去后为0.结果即为16+4=20*/
operate -= (operated<
result += 0x01<
if((operate == 0) || (operate
break;
}
}
printf("%d / %d = %d\r\n", x, y, result);
return operate;
}
使用main函数调用上面两个函数:
void main()
{
int operate/*乘/除数*/, operated/*被乘/除数*/;
while(1)
{
printf("\r\n请输入乘/除数与被乘/除数:\r\noperate = ");
scanf("%d", &operate);
printf("operated = ");
scanf("%d", &operated);
multiple(operate, operated);
divide(operate, operated);
}
}
输出结果如下图:
乘法设计基本思想:类似于小学所学的拆分组合法,在单片机中数据的存储都是以二进制形式存储的,如10=0x0a=00001010B, 23=0x17=0x00010111. 将数据拆分成2的n次方的和(观察数据的二进制存储,发现一定可以拆分)
例如:
2*10=2*(8+2)=(2<<(8在二进制中所在位置) + 2<<(2在二进制中所在位置) )=(2<<4 )+ (2<<2) = 20
2*23=2*(16+4+2+1)=(2<<(16在二进制中所在位置) +2<<(4在二进制中所在位置) + 2<<(2在二进制中所在位置)+ 2<<(1在二进制中所在位置) )=(2<<5) + (2<<3) +(2<<2) + (2<<1) =46
除法设计基本思想:为了尽量提高操作效率,首先确定最少操作次数,观察除数的二进制,从左往右,第一个1所在位置即是最少操作次数10<(2<<4),23<(2<<5)
例如:
60/3 = (48+12)/3 = (16*3 + 4*3)/3 = 20;
23/3 = (12+6+5)/3 = (4*3 + 2*3)/3 + 5/3 = 6...5
结合代码多体会体会,或者VC单步调试,相信可以理解的。
个人感悟,不一定效率最高,如果有更好的方法,欢迎交流,下班下班。
wjx943_536273043 2019-4-3 20:59
1069886355_608129668 2018-11-23 08:29
{
operate -= (operated<<i);
result += 0x01<<i;
if((operate == 0) || (operate<y))
break;
}
1069886355_608129668 2018-11-23 08:25
1069886355_608129668 2018-11-23 08:24
1069886355_608129668 2018-11-23 08:23
wjx943_536273043 2018-11-21 20:58
moniqiuwen 2018-11-21 09:13