打印
[技术问答]

单片机C语言快速精度除法方案

[复制链接]
1488|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
IversonCar|  楼主 | 2016-3-22 21:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
目前的51单片机在进行带小数点结果的除法一般可以采用浮点数计算的方式,但是浮点数计算有一个缺点就是非常耗时,在对时间要求严格的工况就不太适用。
笔者的工作室长期承接单片机、电路、机电液、工控、自动化、计算机软件等项目,最近做了个单片机计算器的设计,在设计除法时利用长整形除法和取余运算,可以得到若干小数位的精度运算,与大家共享。
设计思路如下:
假设长整形除数a,  长整形被数b,步骤如下:
<1>得到除法的整数部分,c=a/b;
<2>设d为a%b,e=10*d,
得到除法的第一位小数,f=e/b;
(要点:将a余b的余数乘以10倍,再和被除数b相除,就得到小数点后一位小数)
<3>设g为e%b,h=10*g,
得到除法的第二位小数,i=h/b;
以此类推,可以得到除法的任意小数……
/**********************************下面附上C语言程序
**********************************************************/
unsigned long result, result_p;//表示除法结果的整数和小数部分
// result_p是小数部分,例如result_p=12345678,表示0.12345678
Void chufa(unsigned long chushu, unsigned long beichushu, unsigned char wei)
// wei表示精确到小数点后多少位
{ unsigned char i;
unsigned long tmp;
result=result_p=0;
if (beichushu!=0)//被除数必须不为0
{
if (wei==0)
{result=chushu/beichushu;//计算整数部分
result_p=0;
}
else
{result=chushu/beichushu;//计算整数部分
tmp=chushu%beichushu;
for (i=1;i<=wei;i++)//计算小数部分
{tmp=tmp*10;
result_p=result_p*10+tmp/beichushu;
tmp=tmp%beichushu;
}
}
}


沙发
643757107| | 2016-3-22 22:16 | 只看该作者
这种算法只是精度提高了,可以这样想,我们直接用人工计算的步骤,在计算机上进行实现。也是可以的。

使用特权

评论回复
板凳
gejigeji521| | 2016-3-22 22:53 | 只看该作者
#include <stdio.h>
#include <string.h>
#include <list>
using namespace std;
void convert(char *a,list<int> &a1)
{/*转换函数*/
     a1.clear();
     int len=strlen(a);
     int i;
     for(i=0;i<len;i++)
     a1.push_back(a[i]-'0');
     while(*a1.begin()==0) a1.pop_front();
}
void print(list<int> &a)
{   /*打印函数*/
     list<int>::iterator it;
     it=a.begin();
     if(a.empty()) {printf("0\n"); return;}
     for(it;it!=a.end();it++)
         printf("%d",*it);
     printf("\n");
}
void sub(list<int> &a,list<int> &b, list<int> &c)
{ /*大整数的减法*/
     c.clear();
     list<int>::reverse_iterator rita=a.rbegin();
     list<int>::reverse_iterator ritb=b.rbegin();
     short carry=0;
     int temp;
     while(rita!=a.rend()&&ritb!=b.rend())
     {
         temp=*rita-*ritb+carry;
         if(temp<0)
         {
             temp+=10; carry=-1;
         }
         else carry=0;
         c.push_front(temp);
         rita++;
         ritb++;
     }
     while(rita!=a.rend())
     {
         temp=*rita+carry;
         if(temp<0) { temp+=10; carry=-1;}
         else carry=0;
         c.push_front(temp);
         rita++;
     }
     while(*c.begin()==0) c.pop_front();
   
}
bool compare(list<int> &a,list<int> &b)
{   /*大整数的比较*/
     if(a.size()>b.size()) return true;
     else if(a.size()<b.size()) return false;
     else
     {
         list<int>::iterator ita=a.begin(),itb=b.begin();
         while(ita!=a.end())
         {
             if(*ita>*itb) return true;
             else if(*ita<*itb) return false;
             else { ita++; itb++;}
         }
         return true;
     }
}
void divid(list<int> &a,list<int> &b, list<int> &c)
{   /* 大整数的除法*/
      c.clear();
      list<int> row,temp;
      list<int>::iterator ita,itc=c.begin();
      int count;
      for(ita=a.begin();ita!=a.end();ita++)
      {        
          count=0;
          while(*row.begin()==0) row.pop_front();
          row.push_back(*ita);
          while(compare(row,b))
          {
              count++;
              sub(row,b,temp);
              row=temp;
          }
          c.push_back(count);
      }
      while(*c.begin()==0) c.pop_front();
}
   
int main()
{
     char sa[901],sb[901];
     list<int> a,b,c;
     while(scanf("%s%s",sa,sb)==2)   
     {
         convert(sa,a);
         convert(sb,b);
         divid(a,b,c);
         print(c);
     }      
     return 0;


使用特权

评论回复
地板
仙女山| | 2016-3-23 20:29 | 只看该作者
一般是能用加减的不用乘除,多用左移或者右移

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

344

帖子

0

粉丝