原创 快速实现乘、除运算的算法(适用于单片机等计算能力有限的系统)。 ...

2018-11-19 22:30 2546 12 14 分类: MCU/ 嵌入式 文集: 记录学习的感悟
从学习单片机以来,就一直被强调,单片机计算能力有限,进行数据乘、除操作十分耗费资源。
本人最近在研究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单步调试,相信可以理解的。
个人感悟,不一定效率最高,如果有更好的方法,欢迎交流,下班下班。
广告

文章评论 7条评论)

登录后参与讨论

wjx943_536273043 2019-4-3 20:59

分享

1069886355_608129668 2018-11-23 08:29

if(operate >= (operated<<i))
                {
                        operate -= (operated<<i);
                        result += 0x01<<i;
                        if((operate == 0) || (operate<y))
                                break;
                }

1069886355_608129668 2018-11-23 08:25

应该是:(operated<<i)

1069886355_608129668 2018-11-23 08:24

代码上传给传漏了!(operated<

1069886355_608129668 2018-11-23 08:23

moniqiuwen: 下班好晚。注意休息啊。
程序猿懂程序猿,比心

wjx943_536273043 2018-11-21 20:58

分享

moniqiuwen 2018-11-21 09:13

下班好晚。注意休息啊。
相关推荐阅读
1069886355_608129668 2018-11-02 19:42
绝对路径与相对路径的区别(相对路径的理解)
本人之前一直理解不了相对路径的概念与使用方法,做项目一直使用的是用绝对路径(在项目中添加头文件包含或者引用路径),也一直没出什么问题,就没怎么在意。 直到最近在做项目的过程中,由于在自己办公电脑上开...
1069886355_608129668 2018-10-31 17:02
基于VS2015的MFC设计中保证列表框始终显示最底行的方法
由于项目需要,使用VS2015的MFC功能编写上位机,过程中使用了 CListCtrl 控件,随着控件中item数量的增加,每次刷新界面之后,都会导致列表界面始终从最上行开始显示,给上位机使...
1069886355_608129668 2018-08-23 10:36
C80C51F340可以通过编译却无法程序却无法运行的原因
前段时间在做一个基于C8051系列单片机的一个项目,将遇到的问题记录一下。1、在编写C8051f340单片机程序的过程中,全局变量的数量不能定义太多。否则会出现可以通过编译,但在仿真、运行过程中发现无...
广告
我要评论
7
12
广告
关闭 热点推荐上一条 /2 下一条