DSP定点数的计算规则和示例

2023-11-06

目录

1. Q/S表示法的数值范围

2. 定点化加减法计算规则

2.1 防溢出处理

3. 定点化乘法计算规则

3.1 推算

4. 定点化除法计算规则

4.1 推算

5. 程序代码中如何确定Q值

6. 浮点转定点计算示例


1. Q/S表示法的数值范围

Q表示法

S表示法

数的范围

Q15

S0.15

-1≤X≤0.9999695

Q14

S1.14

-2≤X≤1.9999390

Q13

S2.13

-4≤X≤3.9998779

Q12

S3.12

-8≤X≤7.9997559

Q11

S4.11

-16≤X≤15.9995117

Q10

S5.10

-32≤X≤31.9990234

Q9

S6.9

-64≤X≤63.9980469

Q8

S7.8

-128≤X≤127.9960938

Q7

S8.7

-256≤X≤255.9921875

Q6

S9.6

-512≤X≤511.9804375

Q5

S10.5

-1024≤X≤1023.96875

Q4

S11.4

-2048≤X≤2047.9375

Q3

S12.3

-4096≤X≤4095.875

Q2

S13.2

-8192≤X≤8191.75

Q1

S14.1

-16384≤X≤16383.5

Q0

S15.0

-32768≤X≤32767

注:

2. 定点化加减法计算规则

加减法,首先要做的是对标,也就是Q值相同才能进行加减法。

(1)加法

如果两个参与运算的加数Q值不同,则首先要进行小数点的调整,数学表达式推算:

 故定点加法的伪代码描述如下:

Int x,y,z;

Long temp;

Temp=y<<(Qx-Qy);

Temp=x+temp;

If(Qx≥Qz)

z=(int)(temp>>( Qx- Qz))

else if(Qx≤Qz)

z=(int)(temp<<( Qz- Qx))

else

示例代码:

#include <stdio.h>
#include <stdlib.h>
#define Q15 32768.0
#define Q13 8192.0

int main()
{
	float x=0.5;
	float y=3.1; //结果3.6-->Q13

	short x_Qx=(short)(x*Q15+0.5);
	short y_Qx=(short)(y*Q13+0.5);
	short z_Q13;

//	printf("%d\n", x_Qx);
//	printf("%d\n", y_Qx);
	long temp;
	temp=y_Qx<<2;
	temp=temp+x_Qx; 
	z_Q13=(int)(temp>>2);
	printf("res:%f\n", z_Q13/Q13);

    return 0;
}

结果:res:3.599976

(2)减法

代码示例

#include <stdio.h>
#include <stdlib.h>
#define Q15 32768.0
#define Q13 8192.0

int main()
{
	float x=3.0;
	float y=3.1; //结果x-y=-0.1-->Q15

	short x_Qx=(short)(x*Q13+0.5);
	short y_Qx=(short)(y*Q13+0.5);
	short z_Q15;

//	printf("%d\n", x_Qx);
//	printf("%d\n", y_Qx);
	long temp;
	temp=x_Qx-y_Qx; //

	z_Q15=(int)(temp<<2);
	printf("res:%f\n", z_Q15/Q15);

    return 0;
}

结果:res:-0.099976

2.1 防溢出处理

整型数进行加减运算的时候,如果得到的结果超出范围:-32768≤X≤32767,即[8000H-7FFFH]

则称之为上溢或者下溢。

(1)下溢:

x=32766, y=3,x和y均从浮点数转换而来,假设它们是同一个Q值,进行加法操作后,结果为:32769,假设这里的数值都是16bit的,那么32769的补码就是:

1000000000000001

计算机将该值取出时,会把它当成一个负数(最高位符号位为1):除去符号位,其余位减1得到:0000 0000 0000 000

再取反,得到:1111 1111 1111 111,为-32767d

所以,若将该数加上1,并不是32770,而是-32766。

测试代码:

#include <stdio.h>

#include <stdlib.h>

int main()

{

short x=32766;

short y=3;

short z=x+y;

printf("z=%d\n", z);

    return 0;

}

结果:z=-32767

(2)上溢

设x=15000,y=20000,则求和后z=x+y=35000 > 32767,如果结果超出16bit的表示范围,则保留32bit的结果(转成32bit数进行运算)。

首先,进行定标(16bit):Qx=1, Qy=0, Qz=0

定点加法先定标,y向x对齐:long temp=y<<1=20000<<1=40000

进行加法:temp=temp+(x<<1);//相当于两个加数同时左移

最后,结果:temp=temp>>1; //Qx>Qz

测试代码:

#include <stdio.h>

#include <stdlib.h>

int main()

{

short x=15000, y=20000;

int temp, z;

temp=(y<<1);

temp=(x<<1)+temp;

z=temp>>1;

printf("z=%d\n", z);

    return 0;

}

结果:z=35000

结果超范围,则两个加数同时左移,最后同时右移,结果不在用16bit来存储,而是32bit。伪代码如下:

Int x,y;

Long temp, z;

Temp=y<<(Qx-Qy); //假设Qx>Qy,y向x对标,y就要左移操作(上文数学表达式推算)。

Temp=x+temp;

If(Qx≥Qz)

z=(int)(temp>>( Qx- Qz))

else if(Qx≤Qz)

z=(int)(temp<<( Qz- Qx))

else

另一种做法是,保持16bit的运算(虽然对结果进行了检查):

#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

int16_t Q16_add_sat(int16_t a, int16_t b)

{

    int16_t result;

    int32_t tmp;

    tmp = (int32_t)a + (int32_t)b;

    if (tmp > 0x7FFF)

        tmp = 0x7FFF;

    if (tmp < -1 * 0x8000)

        tmp = -1 * 0x8000;

    result = (int16_t)tmp;

    return result;

}

int main()

{

short x=15000, y=20000;

// int temp, z;

// temp=(y<<1);

// temp=(x<<1)+temp;

// z=temp>>1;

// printf("z=%d\n", z);

printf("z=%d\n", q_add_sat(x,y));

    return 0;

}

结果:z=32767,精度严重恶化。

修改如下:

int32_t Q16_add_sat(int16_t a, int16_t b)

{

    int32_t result;

    result = (a<<1) + (b<<1);

    result = (result>>1);

    return result;

}

int main()

{

short x=15000, y=20000;

// int temp, z;

// temp=(y<<1);

// temp=(x<<1)+temp;

// z=temp>>1;

// printf("z=%d\n", z);

printf("z=%d\n", Q16_add_sat(x,y));

    return 0;

}

3. 定点化乘法计算规则

3.1 推算

 所以,定点乘法伪代码如下:

Int x,y,z;

Long temp;

Temp=long(x);

z=(temp*y)>>();

测试代码:

#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

#define Q10 1024.0

#define Q9 512.0

#define Q5 32.0

int main()

{

float x=18.4, y=36.8;

long temp;

short x_Q16=x*Q10;

short y_Q16=y*Q9;

short res;

temp=x_Q16*y_Q16;

res=temp>>(10+9-5);

printf("res=%d, %f\n", res, res/32.0);

    return 0;

}

结果:res=21666, 677.062500

4. 定点化除法计算规则

4.1 推算

 测试代码:

#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

#define Q15 32768.0

#define Q10 1024.0

#define Q9 512.0

#define Q5 32.0

int main()

{

float x=18.4, y=36.8;

long temp;

short x_Q16=x*Q10;

short y_Q16=y*Q9;

short res; //Q15

temp=(x_Q16<<(15-10+9));

res=temp/y_Q16;

printf("res=%d, %f\n", res, res/Q15);

    return 0;

}

结果:res=16384, 0.500000

5. 程序代码中如何确定Q值

6. 浮点转定点计算示例

示例1:混合计算

计算1.78x0.6+2.43

代码:

#include <stdio.h>

#include <stdlib.h>

#define Q13_a (0.35*8192.0)

#define Q13_b (2.7*8192.0)

#define Q13_c (1.43*8192.0)

void main()

{

int a,b,c,d,f;

long result;

a=(int)Q13_a;

b=(int)Q13_b;

c=(int)Q13_c;

result=(long)(a*b);

d=(result>>13);

f=d+c;

printf("result:%f\n", f/8192.0);

}

示例2:汉明窗的计算

示例3:FIR低通滤波实现

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DSP定点数的计算规则和示例 的相关文章

随机推荐

  • 大厂领导为什么喜欢跨层与下属聊天

    作为一个在大厂里面浸淫十几年的loser 平时主要精力没用在技术提升上 对于大厂的人情世故各类八卦倒是研究的透彻 如果你细心观察 会发现一些大的公司里面 领导喜欢跨层与下属去沟通聊天 我待过几家比较大的公司 这个现象还是比较普遍 今天就摆一
  • 基于物联网的视觉暂留风扇设计

    论文下载 知网链接 版权所有 有相关问题或索要完整代码实现请联系作者gzn00417或邮箱gzn00417 foxmail com 基于物联网的视觉暂留风扇设计 郭茁宁1 林亦宁2 何胜阳2 哈尔滨工业大学计算机科学与技术学院 黑龙江 哈尔
  • I - LCM of GCDs(约数)

    I LCM of GCDshttps vjudge csgrandeur cn problem AtCoder arc124 c思路 枚举其a 1 和b 1 所有因数 就是将其归类到红蓝两个袋子里去 然后依次判断一对 a i b i 中是否
  • 关于响度、响度级、声强、声强级、声压、声压级、分贝、方、电平、增益、音高、音分

    在录音声学里 响度 响度级 声强 声强级 声压 声压级 分贝 方 电平 增益 音高 音分总是令人头疼的若干概念 这里简单的说一下他们的意义和区别 让我们把它们的顺序整理一下 分贝 分贝是声级测量中最常用的单位 被简写为dB 其中小写的d代表
  • 牛客网-坐标移动

    题目描述 开发一个坐标计算工具 A表示向左移动 D表示向右移动 W表示向上移动 S表示向下移动 从 0 0 点开始移动 从输入字符串里面读取一些坐标 并将最终输入结果输出到输出文件里面 输入 合法坐标为A 或者D或者W或者S 数字 两位以内
  • Android性能篇之(八)Android内存溢出/泄漏常见案例分析及优化方案最佳实践总结

    内存溢出是Android开发中一个老大难的问题 相关的知识点比较繁杂 绝大部分的开发者都零零星星知道一些 但难以全面 本篇文档会尽量从广度和深度两个方面进行整理 帮助大家梳理这方面的知识点 基于Java 一 Java内存的分配 这里先了解一
  • Camera.ScreenToWorldPoint方法介绍

    Camera ScreenToWorldPoint方法介绍 Camera ScreenToWorldPoint是Unity中的一个方法 用于将屏幕坐标系中的点转换为世界坐标系中的点 这个方法通常用于将鼠标点击的位置 屏幕坐标系 转换为游戏世
  • 使用WPS Office模糊处理图片-可用作浏览器背景

    前文转到 给浏览器设置一个图片背景 主题 使用WPS Office模糊处理图片 可用作浏览器背景 步骤如下 1 打开WPS Office 新建一个空白PPT 或者右键 新建 PPT演示文稿 2 将你的图片插入到空白页上 点击 插入 形状 矩
  • xssgame第六关至第八关

    第六关 先试试a标签 可以看到 a标签这里被转义了 再试试其他标签 nm use ver alert 1 转换大小写 成功过关 第七关 可以看到 过滤掉了script 于是采取重复嵌套的方式 第八关 首先 测试script 发现点击添加友情
  • Password Validation using regular expressions(JavaScript)

    Including digit check uppercase check lowercase check the length of password check blank check
  • CentOS7常用工具包安装

    CentOS7常用工具包安装 环境 CentOS 7 9 工具 Xshell7 1 wget下载工具 yum y install wget 2 gcc nginx之类由c语言开发的 编译的时候需要用到 yum y install gcc g
  • 求n的阶乘的方法

    n 1 2 3 4 n 具体来说1 2后再乘3再乘4 依次下去 1 首先用循环的方式 include
  • Linux下备份文件到其他服务器

    最近遇到需求 需要定时将文件备份到其他服务器 于是记录一下 本文旨在描述如何通过rsync插件实现服务器之间的文件备份 以下统一将备份文件所在服务器称为 源服务器 接收备份文件的服务器为 目标服务器 目录 一 为什么用rsync 二 安装r
  • 51单片机学习:外部中断0实验

    实验名称 外部中断0实验 接线说明 实验现象 下载程序后 当按下K3键可控制D1指示灯亮灭 注意事项 将红外接收传感器取下 防止对P3 2口干扰 include reg52 h typedef unsigned int u16 对系统默认数
  • JS中如何跳出.forEach循环

    写在前面 提到在一段程序中如果碰到需要终止 结束一个循环 函数或者一段代码 一般会想到以下这几个关键字return continue break 简述一下三者的区别 break 终止整个循环 有内层循环时终止的是内层循环 退出switch语
  • cpu运行gpu上的pytorch 报错:AssertionError:torch not compiled with cuda enabled——已解决

    感觉今天介绍的这种方法可以解决所有这种报错出现的问题 事件发生 报错 AssertionError torch not compiled with cuda enabled 解决方法 后来看到这个代码 parser add argument
  • uniapp:组件间传值

    组件间传值的情况 子组件 父组件 父组件 子组件 普通组件 普通组件 1 父组件 子组件 father vue
  • 深度了解特征工程

    一 特征工程介绍 Feature Engineering 什么是特征工程 特征工程解决了什么问题 为什么特征工程对机器学习很重要 怎么做特征工程 怎么做好特征工程 集众多博友智慧 一文全面了解并应用特征工程 1 定义及意义 1 定义 特征工
  • icmp隧道工具之ptunnel使用

    一 ptunnel 攻击机A 192 168 137 135 安装ptunnel 跳板机B 192 168 137 130 安装ptunnel 靶机 C 192 168 137 133 1 安装支持库 yum install libpcap
  • DSP定点数的计算规则和示例

    目录 1 Q S表示法的数值范围 2 定点化加减法计算规则 2 1 防溢出处理 3 定点化乘法计算规则 3 1 推算 4 定点化除法计算规则 4 1 推算 5 程序代码中如何确定Q值 6 浮点转定点计算示例 1 Q S表示法的数值范围 Q表