学编程是学java还是学python,初学者学java还是python

  学编程是学java还是学python,初学者学java还是python

  介绍

  本应用笔记介绍了如何使用ARM C编译器和ARM或精简汇编来创建高效的算术代码。因为ARM的核心是整数处理器,所以所有的浮点运算都必须用整数运算来模拟。用定点算法代替浮点数,可以大大提高很多算法的性能。

  本文件包含以下部分:

  定点运算原理:描述定点运算所需的数学概念。

  例如,给出了一个制作信号处理和图形处理定点代码的例子。这是两种最常见的用法。

  c:涵盖了在c中实现定点代码的实际细节。示例程序提供了一组宏定义。

  汇编程序:介绍一个汇编程序的例子。

  定点算法原理

  在计算数学中,一对整数(n,e)(尾数和指数)可以用来近似分数。这是一个整数,代表分数n2e。e可以认为N的位数必须移动到二进制小数点之前。例如

  我是尾数(n)

  这是博览会(e)

  伯尼(Bernard的昵称)(m.)

  最差的

  01100100

  -1

  011001000.

  200

  01100100

  0

  01100100.

  100

  01100100

  一个

  0110010.0

  50

  01100100

  2

  011001.00

  25

  01100100

  三

  01100.100

  12.5

  01100100

  七

  0.1100100

  0.78125

  如果e是一个变量,保存在寄存器中,编译时未知,(n,e)称为浮点数。如果事先知道e,(n,e)称为编译时的固定点数。通过存储尾数,可以将定点存储在标准整数变量(或寄存器)中。

  关于常数点,指数E通常用字母q表示,下面几节描述如何对两个常数进行基本的算术运算。两个算法是a=n2pa=n2p和b=m2qb=m2q,结果表示为c=k2rc=k2r。其中p、q和r是固定的常数指数。

  计算时,只需对尾数n m进行两次计算即可得到k .其中它们的指数用于转换。存储实际数时,只存储尾数。索引由另一个相应的数字保存。

  指数变化

  对定点数执行的最简单的操作是改变索引。为了将索引从P变为R(执行操作c=a),可以通过简单的移位从N计算出随机数K。

  因为n2p=n2rp2r n2p=n2rp2r

  k=n=p(if ) r=p))))).

  k=n(pr ) k=n ) pr ) if ) pr ) if(pr))

  加法和减法

  要运算c=a b,先把A和B变换成和C一样的指数R,然后把尾数相加。这个方法如下。

  N2RM2R=(NM ) N2RM2R=(NM ) 2R

  减法相似性

  增加

  乘积c=ab可以通过简单的整数乘法来实现。方程式如下。

  ab=N2 pm 2 q=(nm)2))PQ)ab=N2 pm 2 q=(nm)2(PQ))))65

  因此,乘积n * m是指数p q的答案的尾数。要将答案转换为指数r,请如上所述进行移位。例如

  k=(nm))pQR)k=(nm))pQR)if)pq=r)if)pq=r)

  分开

  C=a/b也可以通过简单的整数除法来进行。公式如下。

  a/b=(N2P)/M2Q))n/m)2qp=)n/m)2r qp2ra/b=(n2p)/M2Q))n/m)2r qp2r)

  为了不损失精度,必须在除以m之前执行2r qp2r qp乘法。例如,

  k=(n=p ) if ) rq=p).

  平方根

  平方根的公式如下。

  a=N2P=N22RP2ra=N2P=N22RP2R

  换句话说,isqr是整数的平方根函数(例如c=ac=a执行isqr(n2RP) k=isqr) n2RP)。

  溢出

  上式展示了只使用整数运算对定点数进行加、减、乘、除、开方等基本运算的方法。但是,为了在2r2r()表示的结果中准确存储答案,必须保证在计算过程中不会发生溢出。如果不仔细选择指数,每左移一次,加/减或乘就会溢出,成为无意义的答案。

  下面这个“真实世界”的例子说明了如何选择一个指数。

  例子

  信号处理

  在信号处理中,数据通常由-1和1之间的分数组成。

  本例使用指数Q和32位整数尾数(这样每个值都可以保存在ARM寄存器中)。要能够将两个数相乘而不溢出,需要2q32或者q=15。实际上,通常选择q=14,因为它允许多次累加相乘,而没有溢出的风险。

  在编译时固定q=14。那么0xFFFFC000代表-1,0x00004000代表1,0x00000001代表214214,最精确的除数。

  假设x,y是两个q=14尾数,n,m是两个整数。通过应用上面的公式,您可以得到基本操作,其中a为正常的整数:

  操作

  产生q=14格式的答案尾数的代码

  x y

  x y

  x a

  x (a14)

  辅助放大器(辅助放大器的缩写)

  x*a

  正常男性染色体组型

  (x*y)14

  x/a

  x/a

  a/b

  (a14)/b

  x/y

  (x14)/y

  xx

  sqr(x14)

  图像处理

  在这个例子中,(x,y,z)坐标以八位小数信息(q=8)以小数形式存储。如果x存储在一个32位寄存器中,那么x的最低字节给出小数部分,最高的三部分是整数部分。

  要计算距离原点的距离d,以q=8的形式:d=x2 y2 z2-d=x2 y2 z2

  如果您直接应用上述公式并将所有中间答案以q=8的形式保存,则会得到以下代码:

  x=(x*x)8平方x

  y=(y*y)8平方y

  z=(z*z)8平方z

  s=x y z平方和

  d=sqrt(S8)q=8形式的距离

  一

  2

  3

  四

  5

  或者,如果您将中间答案保持为q=16格式,则减少班次数并提高准确度:

  q=16形式的x=x*x的平方

  y=y * y q=16形式的y的平方

  q=16形式的z=z*z的平方

  s=x y x q=16形式的平方和

  d=q=8形式的sqr(s)距离d

  一

  2

  3

  四

  5

  总结

  如果你以q形式相加两个数字,它们将保持q型。

  如果你用q形式乘以两个数字,答案是2q形式。

  如果你采用q形式的数字的平方根,答案是q/2形式。

  要从q型转换为r型,你需要向左移(r-q)或向右移(q-r),取决于q和r中哪一个更大

  要获得最佳精度结果,请选择最大的问,并保证中间计算不能溢出。

  C程序

  可以使用标准整数算术运算在C中对定点算术进行编程,并且当需要时(通常在确保答案仍然是q形式之前或之后的操作之前或之后)使用移位来改变问-形式。

  为了使编程更容易阅读,已经定义了一组C宏。下面的示例程序定义了这些宏并说明了它们的用法:

  注:编译需要在末尾加上-lm选项,如(同groundcontrolcenter)地面控制中心固定值

  /*一个简单的C程序,用来说明定点运算的用法*/

  #包括

  #包括

  #包括

  /*定义宏*/

  /*对固定的两个数a和b执行的基本操作

  点q格式返回q格式的答案*/

  #定义FADD(a,b) ((a) (b))

  #定义FSUB(a,b) ((a)-(b))

  #定义FMUL(a,b,q) (((a)*(b))(q))

  #定义FDIV(a,b,q)

  /*基本运算,其中a是定点q格式,b是

  整数*/

  #定义FADDI(a,b,q) ((a) ((b)

  #定义FSUBI(a,b,q)((a)-(b)

  #定义FMULI(a,b) ((a)*(b))

  #定义FDIVI(a,b) ((a)/(b))

  /*将a从雌三醇环戊醚格式转换为q2格式*/

  #定义FCONV(a,q1,q2) (((q2)(q1))?(a)((q1)-(q2)))

  /* Q1格式的a和q2格式的b之间的一般操作

  以q3格式返回结果*/

  #定义FADDG(a,b,q1,q2,q3) (FCONV(a,q1,q3) FCONV(b,q2,q3))

  #定义FSUBG(a,b,q1,q2,q3) (FCONV(a,q1,q3)-FCONV(b,q2,q3))

  #定义FMULG(a,b,q1,q2,q3) FCONV((a)*(b),(q1) (q2),q3)

  #定义FDIVG(a,b,q1,q2,q3) (FCONV(a,q1,(q2) (q3))/(b))

  /*在浮点之间来回转换*/

  #定义TOFIX(d,q) ((int)( (d)*(double)(1

  #定义TOFLT(a,q) ( (double)(a)/(double)(1

  #定义测试(修复、FLT、字符串){ \

  a=a1=randint();\

  b=bi=a2=randint();\

  fa=TOFLT(a,q);\

  fa1=TOFLT(a1,Q1);\

  fa2=TOFLT(a2,Q2);\

  fb=TOFLT(b,q);\

  ans1=FIX\

  ans 2=FLT;\

  printf(测试%s\n定点答案=%f\n浮点答案=%f\n ,\

  STR,TOFLT(ans1,q),ans 2);\

  }

  int randint(void) {

  int I;

  I=rand();

  i=i 32767

  if(rand()1)I=-I;

  返回我;

  }

  int main(void) {

  int q=14,q1=15,q2=7,q3=14

  双fa、fb、fa1、fa2

  int a,b,bi,a1,a2;

  int ans1

  双ans2

  /*用一些随机数据测试每个宏*/

  测试(FADD(a,b),fa fb,‘FADD’);

  测试(FSUB(a,b),fa-fb, FSUB );

  TEST(FMUL(a,b,q),fa*fb, FMUL );

  TEST(FDIV(a,b,q),fa/fb, FDIV );

  TEST(FADDI(a,bi,q),fa bi, FADDI );

  TEST(FSUBI(a,BI,q),fa-bi, FSUBI );

  TEST(FMULI(a,bi),fa*bi, f苏比);

  TEST(FDIVI(a,bi),fa/bi, FSUBI );

  TEST(FADDG(a1,a2,q1,q2,q3),fa1 fa2, FADDG );

  TEST(FSUBG(a1,a2,q1,q2,q3),fa1-fa2, FSUBG );

  TEST(FMULG(a1,a2,q1,q2,q3),fa1*fa2, FMULG );

  TEST(FDIVG(a1,a2,q1,q2,q3),fa1/fa2, FDIVG );

  printf(已完成标准测试\ n’);

  /*下面的代码将通过对

  系列(效率不高,但作为示例很有用)并进行比较

  实际值*/

  while (1) {

  printf(请输入要 exp 的数字(1):);

  scanf(%lf ,fa);

  printf( x=%f\n ,fa);

  printf( exp(x)=%f\n ,exp(fa));

  q=14/*设置固定点*/

  a=TOFIX(fa,q);/*获取定点格式的*/

  a1=FCONV(1,0,q);/* a的0次方*/

  a2=1;/* 0阶乘*/

  ans 1=0;/*迄今为止的系列总和*/

  for(bi=0;bi10bi ) { /*做十项级数*/

  int j;

  j=FDIVI(a1,a2);/* a^n/n!*/

  ans1=FADD(ans1,j);

  a1=FMUL(a1,a,q);/*将a的功率增加1 */

  a2=a2 *(bi 1);/*下一阶乘*/

  printf(Stage %d answer=%f\n ,bi,TOFLT(ans1,q));

  }

  }

  返回0;

  }

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: