[技术问答] 单片机C语言快速精度除法方案

[复制链接]
1680|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;
以此类推,可以得到除法的任意小数……
  1. /**********************************下面附上C语言程序
  2. **********************************************************/
  3. unsigned long result, result_p;//表示除法结果的整数和小数部分
  4. // result_p是小数部分,例如result_p=12345678,表示0.12345678
  5. Void chufa(unsigned long chushu, unsigned long beichushu, unsigned char wei)
  6. // wei表示精确到小数点后多少位
  7. { unsigned char i;
  8. unsigned long tmp;
  9. result=result_p=0;
  10. if (beichushu!=0)//被除数必须不为0
  11. {
  12. if (wei==0)
  13. {result=chushu/beichushu;//计算整数部分
  14. result_p=0;
  15. }
  16. else
  17. {result=chushu/beichushu;//计算整数部分
  18. tmp=chushu%beichushu;
  19. for (i=1;i<=wei;i++)//计算小数部分
  20. {tmp=tmp*10;
  21. result_p=result_p*10+tmp/beichushu;
  22. tmp=tmp%beichushu;
  23. }
  24. }
  25. }


643757107 发表于 2016-3-22 22:16 | 显示全部楼层
这种算法只是精度提高了,可以这样想,我们直接用人工计算的步骤,在计算机上进行实现。也是可以的。
gejigeji521 发表于 2016-3-22 22:53 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <list>
  4. using namespace std;
  5. void convert(char *a,list<int> &a1)
  6. {/*转换函数*/
  7.      a1.clear();
  8.      int len=strlen(a);
  9.      int i;
  10.      for(i=0;i<len;i++)
  11.      a1.push_back(a[i]-'0');
  12.      while(*a1.begin()==0) a1.pop_front();
  13. }
  14. void print(list<int> &a)
  15. {   /*打印函数*/
  16.      list<int>::iterator it;
  17.      it=a.begin();
  18.      if(a.empty()) {printf("0\n"); return;}
  19.      for(it;it!=a.end();it++)
  20.          printf("%d",*it);
  21.      printf("\n");
  22. }
  23. void sub(list<int> &a,list<int> &b, list<int> &c)
  24. { /*大整数的减法*/
  25.      c.clear();
  26.      list<int>::reverse_iterator rita=a.rbegin();
  27.      list<int>::reverse_iterator ritb=b.rbegin();
  28.      short carry=0;
  29.      int temp;
  30.      while(rita!=a.rend()&&ritb!=b.rend())
  31.      {
  32.          temp=*rita-*ritb+carry;
  33.          if(temp<0)
  34.          {
  35.              temp+=10; carry=-1;
  36.          }
  37.          else carry=0;
  38.          c.push_front(temp);
  39.          rita++;
  40.          ritb++;
  41.      }
  42.      while(rita!=a.rend())
  43.      {
  44.          temp=*rita+carry;
  45.          if(temp<0) { temp+=10; carry=-1;}
  46.          else carry=0;
  47.          c.push_front(temp);
  48.          rita++;
  49.      }
  50.      while(*c.begin()==0) c.pop_front();
  51.    
  52. }
  53. bool compare(list<int> &a,list<int> &b)
  54. {   /*大整数的比较*/
  55.      if(a.size()>b.size()) return true;
  56.      else if(a.size()<b.size()) return false;
  57.      else
  58.      {
  59.          list<int>::iterator ita=a.begin(),itb=b.begin();
  60.          while(ita!=a.end())
  61.          {
  62.              if(*ita>*itb) return true;
  63.              else if(*ita<*itb) return false;
  64.              else { ita++; itb++;}
  65.          }
  66.          return true;
  67.      }
  68. }
  69. void divid(list<int> &a,list<int> &b, list<int> &c)
  70. {   /* 大整数的除法*/
  71.       c.clear();
  72.       list<int> row,temp;
  73.       list<int>::iterator ita,itc=c.begin();
  74.       int count;
  75.       for(ita=a.begin();ita!=a.end();ita++)
  76.       {        
  77.           count=0;
  78.           while(*row.begin()==0) row.pop_front();
  79.           row.push_back(*ita);
  80.           while(compare(row,b))
  81.           {
  82.               count++;
  83.               sub(row,b,temp);
  84.               row=temp;
  85.           }
  86.           c.push_back(count);
  87.       }
  88.       while(*c.begin()==0) c.pop_front();
  89. }
  90.    
  91. int main()
  92. {
  93.      char sa[901],sb[901];
  94.      list<int> a,b,c;
  95.      while(scanf("%s%s",sa,sb)==2)   
  96.      {
  97.          convert(sa,a);
  98.          convert(sb,b);
  99.          divid(a,b,c);
  100.          print(c);
  101.      }      
  102.      return 0;


仙女山 发表于 2016-3-23 20:29 | 显示全部楼层
一般是能用加减的不用乘除,多用左移或者右移
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

344

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部