单片机快速开平方的算法

发布者:闪耀之星最新更新时间:2017-01-18 来源: eefocus关键字:单片机  快速开平方 手机看文章 扫描二维码
随时随地手机看文章

C语言中开平方的算法中要开平方的话,可以在头文件中加#include .然后调sqrt(n);函数即可.但在单片机中要开平方.可以用到下面算法:        

  算法1: 

  本算法只采用移位、加减法、判断和循环实现,因为它不需要浮点运算,也不需要乘除运算,因此可以很方便地运用到各种芯片上去。  


我们先来看看10进制下是如何手工计算开方的。  

先看下面两个算式,  


x = 10*p + q  (1)  

公式(1)左右平方之后得:  


x^2 = 100*p^2 + 20pq + q^2 (2)  

现在假设我们知道x^2和p,希望求出q来,求出了q也就求出了x^2的开方x了。  

我们把公式(2)改写为如下格式:  


q = (x^2 - 100*p^2)/(20*p+q) (3)  

这个算式左右都有q,因此无法直接计算出q来,因此手工的开方算法和手工除法算法一样有一步需要猜值。  


我们来一个手工计算的例子:计算1234567890的开方  


首先我们把这个数两位两位一组分开,计算出最高位为3。也就是(3)中的p,最下面一行的334为余数,也就是公式(3)中的(x^2 - 100*p^2)近似值  


       3    ---------------    | 12 34 56 78 90       9    ---------------    |  3 34  

下面我们要找到一个0-9的数q使它最接近满足公式(3)。我们先把p乘以20写在334左边:  


       3  q    ---------------    | 12 34 56 78 90       9    ---------------  6q|  3 34  

我们看到q为5时(60+q*q)的值最接近334,而且不超过334。于是我们得到:  


       3  5    ---------------    | 12 34 56 78 90       9    ---------------  65|  3 34    |  3 25    ---------------          9 56  

接下来就是重复上面的步骤了,这里就不再啰嗦了。   


这个手工算法其实和10进制关系不大,因此我们可以很容易的把它改为二进制,改为二进制之后,公式(3)就变成了:  



q = (x^2 - 4*p^2)/(4*p+q) (4)  

我们来看一个例子,计算100(二进制1100100)的开方:  


      1  0  1  0    ---------------    | 1 10 01 00      1    --------------- 100| 0 10     | 0 00     ---------------    |   10 011001|   10 01    ---------------            0 00  

这里每一步不再是把p乘以20了,而是把p乘以4,也就是把p右移两位,而由于q的值只能为0或者1,所以我们只需要判断余数(x^2 - 4*p^2)和(4*p+1)的大小关系,如果余数大于等于(4*p+q)那么该上一个1,否则该上一个0。  


下面给出完成的C语言程序,其中root表示p,rem表示每步计算之后的余数,divisor表示(4*p+1),通过a>>30取a的最高 2位,通过a<<=2将计算后的最高2位剔除。其中root的两次<<1相当于4*p。程序完全是按照手工计算改写的,应该不难理解。  


unsigned short sqrt(unsigned long a){  

  unsigned long rem = 0;  

  unsigned long root = 0;  

  unsigned long divisor = 0;  

  for(int i=0; i<16; i++){  

    root <<= 1;  

    rem = ((rem << 2) + (a >> 30));  

    a <<= 2;  

    divisor = (root<<1) + 1;  

    if(divisor <= rem){  

      rem -= divisor;  

      root++;  

    }  

  }  

  return (unsigned short)(root);  

}   



算法2 :单片机开平方的快速算法  


因为工作的需要,要在单片机上实现开根号的操作。目前开平方的方法大部分是用牛顿  

迭代法。我在查了一些资料以后找到了一个比牛顿迭代法更加快速的方法。不敢独享,介  

绍给大家,希望会有些帮助。  


1.原理  

因为排版的原因,用pow(X,Y)表示X的Y次幂,用B[0],B[1],...,B[m-1]表示一个序列,  

其中[x]为下标。  


假设:  

   B[x],b[x]都是二进制序列,取值0或1。  

   M = B[m-1]*pow(2,m-1) + B[m-2]*pow(2,m-2) + ... + B[1]*pow(2,1) + B[0]*pow  

(2,0)  

   N = b[n-1]*pow(2,n-1) + b[n-2]*pow(2,n-2) + ... + b[1]*pow(2,1) + n[0]*pow  

(2,0)  

   pow(N,2) = M  


   (1) N的最高位b[n-1]可以根据M的最高位B[m-1]直接求得。  

   设 m 已知,因为 pow(2, m-1) <= M <= pow(2, m),所以 pow(2, (m-1)/2) <= N <=  

pow(2, m/2)  

   如果 m 是奇数,设m=2*k+1,  

   那么 pow(2,k) <= N < pow(2, 1/2+k) < pow(2, k+1),  

   n-1=k, n=k+1=(m+1)/2  

   如果 m 是偶数,设m=2k,  

   那么 pow(2,k) > N >= pow(2, k-1/2) > pow(2, k-1),  

   n-1=k-1,n=k=m/2  

   所以b[n-1]完全由B[m-1]决定。  

   余数 M[1] = M - b[n-1]*pow(2, 2*n-2)  


   (2) N的次高位b[n-2]可以采用试探法来确定。  

   因为b[n-1]=1,假设b[n-2]=1,则 pow(b[n-1]*pow(2,n-1) + b[n-1]*pow(2,n-2),  

2) = b[n-1]*pow(2,2*n-2) + (b[n-1]*pow(2,2*n-2) + b[n-2]*pow(2,2*n-4)),  

   然后比较余数M[1]是否大于等于 (pow(2,2)*b[n-1] + b[n-2]) * pow(2,2*n-4)。这种  

比较只须根据B[m-1]、B[m-2]、...、B[2*n-4]便可做出判断,其余低位不做比较。  

   若 M[1] >= (pow(2,2)*b[n-1] + b[n-2]) * pow(2,2*n-4), 则假设有效,b[n-2] =  

1;  

   余数 M[2] = M[1] - pow(pow(2,n-1)*b[n-1] + pow(2,n-2)*b[n-2], 2) = M[1] -  

(pow(2,2)+1)*pow(2,2*n-4);  

   若 M[1] < (pow(2,2)*b[n-1] + b[n-2]) * pow(2,2*n-4), 则假设无效,b[n-2] =  

0;余数 M[2] = M[1]。  


   (3) 同理,可以从高位到低位逐位求出M的平方根N的各位。  


使用这种算法计算32位数的平方根时最多只须比较16次,而且每次比较时不必把M的各位逐  

一比较,尤其是开始时比较的位数很少,所以消耗的时间远低于牛顿迭代法。  



2. 实现代码  

这里给出实现32位无符号整数开方得到16位无符号整数的C语言代码。  


-------------------------------------------------------------------------------  


/****************************************/  

/*Function: 开根号处理                  */  

/*入口参数:被开方数,长整型            */  

/*出口参数:开方结果,整型              */  

/****************************************/  

unsigned int sqrt_16(unsigned long M)  

{  

    unsigned int N, i;  

    unsigned long tmp, ttp;   // 结果、循环计数  

    if (M == 0)               // 被开方数,开方结果也为0  

        return 0;  


    N = 0;  


    tmp = (M >> 30);          // 获取最高位:B[m-1]  

    M <<= 2;  

    if (tmp > 1)              // 最高位为1  

    {  

        N ++;                 // 结果当前位为1,否则为默认的0  

        tmp -= N;  

    }  


    for (i=15; i>0; i--)      // 求剩余的15位  

    {  

        N <<= 1;              // 左移一位  


        tmp <<= 2;  

        tmp += (M >> 30);     // 假设  


        ttp = N;  

        ttp = (ttp<<1)+1;  


        M <<= 2;  

        if (tmp >= ttp)       // 假设成立  

        {  

            tmp -= ttp;  

            N ++;  

        }  


    }  


    return N;  


以上都是网络查找的资料,有些晦涩难懂,不过在实际运用中可以使用这些算法。


关键字:单片机  快速开平方 引用地址:单片机快速开平方的算法

上一篇:谈谈单片机程序中的自动化测试
下一篇:单片机数码管显示-消影问题

推荐阅读最新更新时间:2024-03-16 15:31

PIC单片机的bank和PC的出错问题
1、 BANK设置错误: 先来看一段程序: include p16f877.inc PORTDB EQU 20H …… START movlw b‘11110000’ movwf PORTDB clrf TRISD MAIN bcf STATUS,C rlf PORTDB,1 btfsc STATUS,C bsf PORTDB,0 movf PORTDB,W movwf PORTD call DELAY goto MAIN …… 上面的是一个将D口的发光二极管循环点亮的小程序,实际运行发现并不能达到点亮的效果。通过设置断点和观察变量的手段发现,单片机在执行“clrf TRISD”这一语句后,T
[单片机]
51单片机-控制LED灯
1.硬件设计 通过原理图分析,LED 采用共阳接法,即所有 LED 阳极管脚接电源 VCC(5V),阴极管脚通过一个限流电阻接到 P2 口上;要让 LED 发光即对应的阴极管脚应该为低电平,若为高电平则熄灭;所以如何配置P2口的高低电平(P2寄存器),就是怎么去控制这8颗LED灯。 2.软件设计 2.1.点亮一颗LED灯 功能需求:点亮D1这一颗LED灯 程序设计:根据原理图去配置对应的寄存器(P2口),去控制LED灯的亮灭状态,如:D1亮,其他灯不亮,即P20输入低电平,其他管脚输入高电平; #include REGX52.H void main() { P2=0XFE;//1111 1110 D1灯亮,其
[单片机]
51<font color='red'>单片机</font>-控制LED灯
力旺MCU绿制程 降低成本
嵌入式非挥发性硅智财(eNVM IP)供应商力旺电子(3529)昨(20)日宣布,针对微控制器(MCU)推出绿制程平台,协助晶圆代工厂大幅简化制造流程,力旺已提供单次可程式(OTP)及多次可程式(MTP)硅智财解决方案,不仅制程可推进至0.153微米,还可有效减少光罩数及降低约30%成本。 力旺协助晶圆代工厂建构绿制程平台,在针对MCU特定应用减除非必要之元件后,将传统需花费至少27道光罩的制程步骤,大幅降低至15道光罩以内,协助客户降低30%以上之成本,特别符合大宗消费性电子产品对低成本MCU要求。 力旺指出,绿制程平台原以8寸晶圆厂0.18微米制程为基础,在今年度更进一步推进至0.153微米的布局设计规范(Design
[单片机]
51单片机模拟串口源程序
单片机模拟串口实验,在没有串口的单片机上想使用串口功能这就需要模拟一个串口了 单片机源程序如下: #include reg51.h typedef unsigned char BYTE; typedef unsigned WORD; typedef bit BOOL; #define BAUD 0xFE80 /* 9600bps@11.0592MHz */ sfr AUXR = 0x8E; sbit RXB = P3^0; /* 定义串口TX RX端口 */ sbit TXB = P3^1; BYTE TBUF,RBUF; BYTE TDAT,RDAT; BYTE TCNT,RCNT
[单片机]
单片机中最小二乘方滤波器的向量测量和功率计算
    摘要: 提供了一种每周波四点采样的最小二乘方滤波器,通过整型变换和查表求根等优化算法,可在单片机中实现相量的快速测量。分析了滤波器中相量的相位关系,并提供了两线制功率的计算方法。     关键词: 最小二乘方滤波器 向量 单片机 功率 目前,以单片机为基础的数字式电气测量、保护装置已成为主流形式。交流信号直接采样也已成为一种普通的方法。快速傅立叶算法是其中的主要算法,而最小二乘方算法,计算量很大,特别是在单片机的处理能力有限的情况下,既要保证实时性,又要保证计算速度,不经过精心设计和程序优化,很难保证二者的统一。 通过减少采样次数、使用每周滤四个采样点拟合的滤波器和一套优化措施,使该算法计算速度大大
[工业控制]
PIC单片机对家庭防盗传感器的设计
PI C12C508/509是8脚封装的8位 单片机 ,极适合于嵌入到各种电子装置中做智能开发,下面介绍二个较为简洁的实例电路,供参考学习。 灯光亮度调节器 根据房间亮度自动调节电灯亮度 手动调节电灯亮度 家庭防盗传感器 非法进入声/光报警 单片机 自动报警/状态保存 手动开启/关闭系统
[单片机]
PIC<font color='red'>单片机</font>对家庭防盗传感器的设计
如何设计一个工作稳定、可靠的基于CY7C68013A单片机的USB控制系统?
引言 通用串行总线(Universal Serial Bus,USB)作为计算机上的新型接口技术,越来越受到人们的青睐。与以前的RS 232,RS 485,ISA,PCI和并行接口等接口相比,USB避免了接口体积大、接口规范不统一、不支持热插拔等缺陷,具有使计算机与外部设备连接十分方便的优点。目前,很多设备都开始使用USB接口来实现,如鼠标、键盘、打印机等。在实际设计工作当中,也越来越多地采用了USB技术,如数据采集等。USB的设计和应用已经成为现代电子设计中一个非常重要的部分。 1 USB 2.0特点 USB是一种高效、快速、价格低廉、体积小的新型串行通信接口,其最大的特点是支持热插拔,可以在不重新启动计算机的情况下直接将U
[单片机]
如何设计一个工作稳定、可靠的基于CY7C68013A<font color='red'>单片机</font>的USB控制系统?
C8051单片机实现多目标超声波测距的设计
超声波测距传感器以其测量精度高、响应快和价格低廉而广泛应用在工业现场测距、移动机器人导航和定位等场合。超声波测距传感器常用的方式是1 个发射头对应1 个接收头,也有多个发射头对应1 个接收头。 它们共同之处是:每个接收头只测量一个位置,这个位置就是除盲区内因发射的超声波旁瓣引起的接收信号超声波包络峰值外,第1个接收信号超声波包络峰值对应的距离。 在机器人自主导航避障时,机器人只关心最近障碍物的距离,是能够完成自主避障的。 但是在机器人定位时,尤其在动态环境下,1 个接收头同时测量多个距离,能够更多地描述环境信息,这对机器人用超声波定位具有重要意义。 1 超声波 1. 1 超声波测距原理 超声波测距原理比较简单,一般是采用时差法
[单片机]
C8051<font color='red'>单片机</font>实现多目标超声波测距的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved