浮点运算
浮点数的运算方法

浮点数的运算方法浮点数是计算机中一种表示实数的数据类型,其特点是可以表示带有小数部分的数字。
在进行浮点数的运算时,需要考虑到浮点数的精度问题、舍入误差以及运算顺序等因素。
浮点数的表示方法为:±m×be,其中m为尾数(即小数部分的数值),b为基数或底数,e为指数(表示位移的量)。
1.浮点数加法运算:-对两个浮点数的指数进行比较,将较小指数的浮点数的尾数左移指数之差的位数,使两个浮点数的小数点对齐。
-对齐后的尾数相加,得到一个和。
-对和进行规格化,即将结果的尾数进行处理,使其满足指定的位数限制。
-对规格化后的结果进行舍入运算,得到最终结果。
2.浮点数减法运算:-先将减数的指数调整与被减数的指数相等。
-对齐后的尾数相减,得到一个差。
-对差进行规格化和舍入运算,得到最终结果。
3.浮点数乘法运算:-将两个浮点数的指数相加,得到加法的和,并相应地调整两个浮点数的尾数。
-尾数相乘,得到一个乘积。
-对乘积进行规格化和舍入运算,得到最终结果。
4.浮点数除法运算:-将被除数的指数减去除数的指数,得到差,并相应地调整两个浮点数的尾数。
-尾数相除,得到一个商。
-对商进行规格化和舍入运算,得到最终结果。
在进行浮点数运算时需要注意一些问题:-浮点数的精度问题:由于浮点数的尾数有限位数,所以会存在精度丢失的问题。
这就意味着进行浮点数运算时,可能会出现舍入误差,导致结果有微小的偏差。
-运算顺序:浮点数的运算顺序可能会影响最终结果。
在连续进行多次浮点数运算时,可能会得到不同的结果。
这是因为浮点数的运算不满足交换律和结合律。
因此,在编程中需要谨慎选择运算顺序,以避免结果的不确定性。
-溢出和下溢问题:由于浮点数的范围限制,可能会出现溢出(结果超出浮点数的表示范围)或下溢(结果过小,无法表示)的情况。
针对这些情况,需要进行特殊处理,如返回特定的错误码或进行科学计数法表示。
在实际编程中,可以使用编程语言提供的浮点数运算库或内置函数来进行浮点数运算,以确保运算结果的准确性和可靠性。
浮点数的四则运算

6
4)舍入 ❖由于X+Y是左规,结果不需要舍入; ❖X-Y为右规,若采用末位恒置1法,则
[X-Y]浮=0011;00100011。 ❖若采用0舍1入法,则结果相同。
7
2.7.2 浮点乘除运算
11
例 设不含阶符的阶码位数n=4,Ex=-1010,Ey=+ 0111,求[Ex±Ey]移。
解: [Ex]移 =000110,[Ey]补 =000111, [-Ey]补 =111001
[Ex+ Ey ]移=[Ex]移 + [Ey]补 =000110+000111= 001101,Ex+ Ey=-0011;
解:先将两浮点数表示为规格化的浮点数: [X]浮=00 01;00 110101 [Y]浮=00 10;11 010110
1)对阶 求阶差△E=0001补-0010补=1111补=-1 Ex<Ey,按小阶对大阶原则,X的尾数右移1位,阶码加1,尾 数舍入采用末位恒置1法,则: [Xห้องสมุดไป่ตู้浮=00 10;00 011011
• 当结果尾数出现01.××…×或10.××…×时,需右 移一位,并使阶码加1,这个过程称为右移规格化, 简称右规。
• 当结果尾数出现00.0××…×或11.1××…×时,需 要进行左移规格化处理,简称左规。左规时尾数左 移一位,阶码减1。
3
浮点加减运算(续)
右规和对阶操作时尾数右移,需要进行舍入处理。 计算机中的舍入方法: ❖ 截断法:
同理: [Ex]移 + [-Ey]补 = [Ex-Ey ]移(mod 2n+1 )
浮点数的运算方法

浮点数在计算机内的格式
X = MX * 2
EX
浮点数: X = M s Es E m-1 ...E1 E 0 M-1 M-2 ...M-n
IEEE 标准:尾数用原码
浮点数是数学中实数的子集合,由一个纯小数乘上一个指数 值来组成。在计算机内,其纯小数部分被称为浮点数的尾数, 对非 0 值的浮点数,要求尾数的绝对值必须 >= 1/2,称满足这 种表示要求的浮点数为规格化表示; 把不满足这一表示要求的尾数,变成满足这一要求的尾数 的操作过程,叫作浮点数的规格化处理,通过尾数移位和修改 阶码实现。
四. 浮点运算器与浮点数运算
浮点运算器通常由 处理阶码的 和 处理尾数的 两个定点运算器组成
在早期的小或微型机中,浮点运算器通常以 任选件方式提供给用户 , 主要用于计算浮点数
浮点数加减运算
对阶 执行加减 规格化 舍入 (右归)判溢出
浮点数乘除运算
阶码加减 尾数乘除 舍入与规格化处理 判溢出
浮点数在计算机内的格式
浮点数格式:关于移码的知识
8 位的阶码能表示-128~+127,当阶码为-128时,其补码表 示为 00000000,该浮点数的绝对值<2-128,人们规定此浮点数的 值为零,若尾数不为 0 就清其为 0,并特称此值为机器零。 一位符号位和 n 位数值位组成的移码, 其定义为; [E]移 = 2n + E -2n<=E<2n 负数 正数 +127 0 表示范围: 00000000 ~ 11111111 8 位移码表示的机器数为数的真值 在数轴上向右平移了 128 个位置
浮点数除运算举例
X=2010*0.1011, Y=2100*(-0.1101) (1)阶码相减: 积的阶码 = EX - EY = EX + (-EY) = 1 010 + 0 100 = 0 110
什么是浮点运算

什么是浮点运算
什么是浮点运算
浮点运算就是实数运算,因为计算机只能存储整数,所以实数都是约数,这样浮点运算是很慢的而且会有误差。
当我们用不同的电脑计算圆周率时,会发现一台电脑的计算较另一台来讲结果更加精确。
或者我们在进行枪战游戏的时候,当一粒子弹击中墙壁时,墙上剥落下一块墙皮,同样的场面在一台电脑上的表现可能会非常的呆板、做作;而在另外一台电脑上就会非常生动形象,甚至与我们在现实中看到的所差无几。
这都是浮点运算能力的差异导致的。
如果是实数的话,就不是这样了,机器有两种办法表示实数,一种是定点,就是小数点位置是固定的,一种是浮点,就是小数点位置不固定,计算方法也比较麻烦,通常会比整数运算代价大很多。
计算机里整数和小数形式就是按普通格式进行存储,例如1024、3.1415926等等,这个没什么特点,但是这样的数精度不高,表达也不够全面,为了能够有一种数的通用表示法,就发明了浮点数。
浮点数的表示形式有点像科学计数法,例如1024就能表示成0.1024×10^4,3.1415926就能表示成0.31415926×10^1,这就是浮点数。
浮点数进行的运算就是浮点运算。
浮点运算比常规运算更复杂,因此计算机进行浮点运算速度要比进行常规运算慢得多。
1。
浮点数的运算方法

阶码位 尾数数码位 总位数
1 1 1
8 11 15
23 52 64
32 64 80
浮点数的阶码的位数决定数的表示范围, 浮点数的阶码的位数决定数的表示范围, 阶码的位数决定数的表示范围 尾数的位数决定数的有效精度 的位数决定数的有效精度。 尾数的位数决定数的有效精度。
浮点数在计算机内的格式
X = MX * 2
负数 正数
[X]补 = X 2n+1 + X 0 ≤ X < 2n -2n ≤ X ≤ 0 0
机器数
浮点数格式:关于移码的知识 浮点数格式:关于移码的知识 移码
8 位的阶码能表示 位的阶码能表示-128~+127,当阶码为 ,当阶码为-128时,其补码表 时 示为 00000000,该浮点数的绝对值 -128,人们规定此浮点数的 ,该浮点数的绝对值<2 人们规定此浮点数的 值为零, 机器零。 值为零,若尾数不为 0 就清其为 0,并特称此值为机器零。 ,并特称此值为机器零 位数值位组成的移码, 其定义为; 一位符号位和 n 位数值位组成的移码 其定义为; [E]移 = 2n + E -2n<=E<2n 负数 正数 +127 0 -128 机器数 表示范围: 00000000 ~ 11111111 表示范围: 8 位移码表示的机器数为数的真值 向右平移了 在数轴上向右平移 在数轴上向右平移了 128 个位置
(2)尾数相除:MX/MY = 0.1011/(-0.1101) )尾数相除: = -0.1101 (3) (4) (5) 已是规格化数 不必舍入 也不溢出 已是规格化数, 不必舍入, 最众的商 [MX]移 = 1 0110 1101, , 即 2-2 *(-0.1101) ( )
浮点数的运算方法

浮点数的运算方法浮点数是计算机中用于表示实数的一种数据类型,由于实数是无限的,而计算机只能存储有限的信息,所以必然存在精度误差。
浮点数的运算涉及到加法、减法、乘法和除法等基本运算,以及开方、幂函数等高级运算。
1.加法运算:浮点数相加时,先将较小的浮点数调整为与较大的浮点数相同的指数,然后进行尾数的相加,最后对结果进行规格化处理,即进行舍入操作,得到最终的结果。
2.减法运算:浮点数相减的原理与加法相同,只是在相减之前,需要将两个浮点数的指数调整为相等,然后进行尾数的相减操作,最后同样需要对结果进行规格化处理。
3.乘法运算:浮点数相乘时,将两个浮点数的指数相加,然后将尾数相乘得到结果的尾数部分,最后对结果进行规格化处理。
4.除法运算:浮点数除法的原理与乘法类似,先将两个浮点数的指数相减,然后将尾数相除得到结果的尾数部分,最后同样需要进行规格化处理。
5.开方运算:浮点数的开方运算是通过求解多项式的根来实现的,常用的方法有牛顿法、二分法和二次近似法等。
这些方法都是通过迭代的方式,逐步逼近平方根的值,直到达到所需的精度。
6.幂函数运算:浮点数的幂函数运算可以通过连乘或连乘的方式实现。
幂函数运算的精度取决于底数和指数的精度以及所需的结果精度。
在浮点数的运算过程中,需要注意以下几个常见问题:1.精度丢失:浮点数的表示是有限的,不可避免地存在精度误差,特别是在进行连续的浮点数运算时,会导致误差累积,可能导致结果的不准确。
2.舍入误差:浮点数的结果需要进行舍入操作以保持一定的精度。
舍入规则有多种,如四舍五入、向上取整、向下取整等,选择合适的舍入规则可以减小误差。
3.溢出和下溢:浮点数的范围是有限的,当计算结果超出范围时,会发生溢出;当结果接近零但无法表示时,会发生下溢。
这两种情况都需要进行特殊处理。
4. 特殊数值:浮点数中有几个特殊的数值,如无穷大(Infinity)、非数值(NaN)和零(0)。
这些特殊值的运算需要按照特定的规则进行处理,以免引起错误。
浮点运算方法和浮点运算器

溢出判断和处理
课堂作业
设[x1]补=11.01100000,
[x2]补=11.01100001, [x3]补=11.01101000, [x4]补=11.01111001,
求执行只保留小数点后4位有效数字的 舍入操作值。
• 例:设X=2001*(-0.111),Y=2010*0. 101 ,求X-Y.(假设两数均以补码表示,阶码采 用3位,尾数采用4位,均包括符号位.)
(4).判溢出 阶码不溢出。所以最终的结果为 X+Y=2011*(-0.101)
2.6.2 浮点乘法和除法运算
设有两个浮点数x和y: x=2Ex· Mx y=2Ey· My x×y=2(Ex+Ey)· (Mx×My) x÷y=2(Ex-Ey)· (Mx÷My) 乘除运算分为四步
浮点加减法运算
舍入
(1) “0舍1入”法,即右移时丢掉的最高位为0,则 舍去;是1,则将尾数的末位加1(相当于进入)。 (2)“恒置1”法,即不管移掉的是0还是1,都把尾数 的末位置1。
溢出处理
阶码最高位为00或11不溢出 [E]补=01 XX…X为上溢,真正溢出,需做溢出处理。 [E] 补=10 XX…X为下溢,浮点数值趋于零,用机器零 表示。
丢失
两个负数相加,结果为正数, 说明产生了溢出.
但是在浮点数的运算中,只有当阶码产生溢出时,才是溢出。 此时只是说明尾数的结果为不规格化数,应进行右规。
(3).规格化和舍入处理
由于结果产生了溢出,应执行右规处理,所谓右规格 化的规则,就是尾数右移1位,阶码加1,所以结果为 1.011(1) ,阶码为011 舍入处理,采用恒舍法处理,则有尾数为1.011
浮点数的运算方法

EX
X = Ms Es Em-1 ...E1 E0 M-1 M-2 ...M-n IEEE 标准:阶码用移码,基为2
按国际电子电气工程师协会规定的国际通用标准,浮点 数的阶码用整数给出,并且要用移码表示,用作为以 2为底 的指数的幂。既然该指数的底一定为 2 ,可以不必在浮点数 的格式中明确表示出来, 只需给出阶码的~+127,当阶码为-128时,其补码表 示为 00000000,该浮点数的绝对值<2-128,人们规定此浮点数的 值为零,若尾数不为 0 就清其为 0,并特称此值为机器零。 一位符号位和 n 位数值位组成的移码, 其定义为; [E]移 = 2n + E -2n<=E<2n 负数 正数 +127 表示范围: 00000000 ~ 11111111 8 位移码表示的机器数为数的真值 在数轴上向右平移了 128 个位置
注意:计算结果的阶码符号位在此变了一次反, 结果为 +6 的 移码
(2)尾数相乘:MX*MY = 0.1011*(-0.1101) = -0.10001111 (3) (4) (5) 已是规格化数, 不必舍入, 也不溢出 最众乘积 [MX]移 = 1 1110 10001111, 即 26 * (-0.10001111)
浮点数在计算机内的格式
X = MX * 2 浮点数: X = M s Es E m-1 ...E1 E 0 M-1 M-2 ...M-n IEEE 标准:尾数用原码
按国际电子电气工程师协会规定的标准,浮点数的尾数要 用原码表示,即符号位 Ms: 0 表示正,1 表示负,且非 0 值尾数 数值的最高位 M-1 必为 1, 才能满足浮点数规格化表示的要求;
(2)尾数求和:00 0011011011 + 11 01010100 11 1000101011
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32-F4属于Cortex-M4构架,与M0、M3的最大不同就是有硬件浮点运算FPU,数学计算速度相比普通cpu运算快上几十倍。
想要使用FPU首先包含#include “arm_math.h”,还有在keil的target选项中勾选use single precision。
1.1 简单的FPU运算性能测试测试条件是开启一个100ms定时器,定时串口打印计算次数,优化级别是0,main函数中运行的代码如下:float a=1.1,b=1.2,c=1.3,d=1.4;1、FPU运算474566次,CPU运算64688次,除法速度快了7.3倍多。
c = b / d;2、FPU运算722169次,CPU运算244271次,乘法运算快了3倍。
FPU的乘法运算比除法运算快1.5倍。
c = b * d;3、FPU运算19398次,CPU运算19628次,FPU的双精度除法运算没有优势,比单精度运算慢了24.5倍c = b / 1.4;4、FPU运算503321次,CPU运算65450次,单精度常数和变量的运算差不多,单精度常数的除法快6%左右,这根编译器的关系比较大。
c = b / 1.4f;5、FPU运算519073次,跟下面比较说明整形常数和单精度常数的除法运算速度几乎一样。
c = b / 3;6、FPU运算519057次c = b / 3.0f;7、FPU运算263643次c = arm_cos_f32(1.3f);8、FPU运算3949次,说明IT给的DSP库运算速度还是很给力的,速度快了67倍c = cos(1.3f);1.2 代码设置旧版本的keil设置如下,但是发现我使用的keil5包含的新固件库已经不需要这一步了。
如果没有启动FPU而使用数学函数运算时,CPU执行时认为遇到非法指令而跳转到HardFault_Handler()中断函数中死循环。
因此,需要在系统初始化时开启FPU。
在system_stm32f4xx.c中的SystemInit()函数中添加如下代码:/* FPU settings ------------------------------------------------------------*/#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */#endif当__FPU_PRESENT=1且__FPU_USED=1时,编译时就加入了启动FPU的代码,CPU也就能正确高效的使用FPU进行简单的加减乘除。
需要使用固件库自带的arm_math.h而非编译器自带的math.h,这个文件根据编译控制项(__FPU_USED ==1)来决定是使用哪一种函数方法:如果没有使用FPU,那就调用keil的标准math.h头文件中定义的函数;如果使用了FPU,那就是用固件库自带的优化函数来解决问题。
1.3编译控制在arm_math.h开头部分有一些编译控制信息:[cpp] view plain copy#ifndef _ARM_MATH_H#define _ARM_MATH_H#define __CMSIS_GENERIC /* disable NVIC and Systick functions */#if defined (ARM_MATH_CM4)#include "core_cm4.h"#elif defined (ARM_MATH_CM3)#include "core_cm3.h"#elif defined (ARM_MATH_CM0)#include "core_cm0.h"#else#include "ARMCM4.h"#warning "Define either ARM_MATH_CM4 OR ARM_MATH_CM3...By Default building on ARM_MATH_CM4....."#endif#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */#include "string.h"#include "math.h"从中可以看出,为了使用STM32F4的arm_math.h,我们需要定义ARM_MATH_CM4;否则如果不使用CMSIS的库,就会调用Keil自带的math.h。
另外,定义控制项__CC_ARM在某些数学函数中会使用VSQRT指令(浮点运算指令),运算速度比Q指令要快很多。
总结一下,需要添加宏定义ARM_MATH_CM4, __CC_ARM。
1.4添加库根据使用的器件和运算模式,添加arm_cortexMxx_math.lib到工程文件中,位于\Libraries\CMSIS\Lib\ARM中。
* The library installer contains prebuilt versions of the libraries in the <code>Lib</code> folder.* - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)* - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)* - arm_cortexM4l_math.lib (Little endian on Cortex-M4)* - arm_cortexM4b_math.lib (Big endian on Cortex-M4)* - arm_cortexM3l_math.lib (Little endian on Cortex-M3)* - arm_cortexM3b_math.lib (Big endian on Cortex-M3)* - arm_cortexM0l_math.lib (Little endian on Cortex-M0)* - arm_cortexM0b_math.lib (Big endian on Cortex-M3)注:如果存储空间不允许,也可以不添加库,只添加\Libraries\CMSIS\DSP_Lib\Source中需要的源文件和arm_math.h。
其他DSP使用示例见\Libraries\CMSIS\DSP_Lib\Examples。
1.5 DSP_Lib的文件结构BasicMathFunctions:提供浮点数的各种基本运算函数,如加减乘除等运算。
对于M0/M3只能用Q运算,即文件夹下以_q7、_q15和_q31结尾的文件;而M4F能直接硬件浮点计算,属于文件夹下以_f32结尾的文件。
CommonTables:arm_common_tables.c文件提供位翻转或相关参数表。
ComplexMathFunctions:复述数学功能,如向量处理,求模运算的。
ControllerFunctions:控制功能,主要为PID控制函数。
arm_sin_cos_f32/-q31.c函数提供360点正余弦函数表和任意角度的正余弦函数值计算功能。
FastMathFunctions:快速数学功能函数,提供256点正余弦函数表和任意任意角度的正余弦函数值计算功能,和Q值开平方运算:FilteringFunctions:滤波函数功能,主要为FIR和LMS(最小均方根)滤波函数。
MatrixFunctions:矩阵处理函数。
StatisticsFunctions:统计功能函数,如求平均值、计算RMS、计算方差/标准差等。
SupportFunctions:支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。
TransformFunctions:变换功能。
包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT (RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。
1.6常用库函数需要包含头文件:#include <arm_math.h>float32_t arm_sin_f32(float32_t x);float32_t arm_cos_f32(float32_t x);static __INLINE arm_status arm_sqrt_f32(float32_t in, float32_t *pOut)使用STM32F4XX自带数学库"arm_math.h"分类:STM32| 标签:STM32 arm_math DSP2013-08-28 16:24 阅读(12285)评论(0)使用STM32F4XX自带数学库"arm_math.h"STM32-F4属于Cortex-M4F构架,这与M0、M3的最大不同就是具有FPU(浮点运算单元),支持浮点指令集,因此在处理数学运算时能比M0/M3高出数十倍甚至上百倍的性能,但是要充分发挥FPU的数学性能,除了#include “arm_math.h”(而非用编译器自带的math.h)以外,(arm_math.h位于\Libraries\CMSIS\Include文件夹)还需要进行设置。
1、代码设置如果没有启动FPU而使用数学函数运算时,CPU执行时认为遇到非法指令而跳转到Hard Fault_Handler()中断函数中死循环。
因此,需要在系统初始化时开启FPU。
在system_ stm32f4xx.c中的SystemInit()函数中添加如下代码:/* FPU settings ------------------------------------------------------------*/#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 F ull Access */#endif2、编译控制从上面的代码可以看出,当__FPU_PRESENT=1且__FPU_USED=1时,编译时就加入了启动FPU的代码,CPU也就能正确高效的使用FPU进行简单的加减乘除了。