日常随记——浮点数与定点数转化程序设计

文章目录

  • 前言
  • 一、浮点数与定点数表示方法
  • 二、转换思路
    • 1.原理分析
    • 2.参考代码
  • 总结


前言

本文旨在讨论float字型向定点数字型转换的具体方案,并以10位小数为例。欠缺测试,欢迎交流讨论


一、浮点数与定点数表示方法

float字型在大多数机器中占位32位,具有1位符号位,8位指数位以及23位尾数位,为计算机提供了约提供了一个大约在 -3.4E-38 ~ 3.4E+38的数据范围。但运算过程中需要频繁运行对点等操作,计算过程需要消耗大量计算资源。而对于许多运算,其精度以及数据范围是确定的,通过定点数的数据存储计数,可以极大的节约计算资源。

float字型记为 1. m ∗ 2 e x p − 127 1.m * 2^{exp-127} 1.m2exp127 ,内容表示如下,通过掩膜0x80000000,0x7F800000,0x007FFFFF可以分别获得对应内容值。

符号位0表述数据为正,1表述数据为负,且不需要取反,直接标志符号。
指数位为无符号整数,内容值为127表示指数为0,128为1,以此类推,即左移exponent - 127位。
尾数表示去掉整数1的数字,数据录入前会将小数位移到第一个1后,该整数1不会计入字型中,小数点后保留23位尾数。

在这里插入图片描述
对应的定点数表示更为简单,其具体小数点根据操作者需求而定,一般会针对一种小数点位置标记一种定点数Qm.n。下图为小数位为10的定点数,正负数通过反码记录。

在这里插入图片描述

二、转换思路

1.原理分析

根据上文所述,将float字型转为Q22.10字型,需要获取其其符号、尾数、指数信息,将小数点归到10位,并根据符号选择是否取反内容值。

对于float型变量,我们可以通过创建一个uint32_t* ptr指针,配合掩膜以获取其符号、尾数、指数信息,其代码如下

	uint32_t* ptr = (uint32_t*)&Src;
	int exponent = ((*ptr & 0x7f800000)>>23) - 127;
	uint32_t mantissa = (*ptr & 0x007fffff)+0x00800000;//float字型尾数部分省略1,需要主动加上
	int sign_bit = (*ptr & 0x80000000);

上述操作皆没有做位移处理,实际上为了实现float字节对定点数的数据变换,需要先将其尾数(0.xxxx)加一,并乘上相应的尾数,即将上文所获得的 mantissa 左移 exponent 或者右移 -exponent ,具体方向应根据 exponent 确定。需要注意的是,此时数据的小数点仍在23位左侧,我们希望将数据转化为拥有X位小数的定点数,则需要将系统继续右移 23-X位。

符号位可以通过判断,在负数情况下通过异或操作实现数据取反。

2.参考代码

代码如下:

typedef int32_t q22_10_t;

q22_10_t my_float_to_q22_10_t(float Src)
{
	q22_10_t temp;
	uint32_t* ptr = (uint32_t*)&Src;
	
	int32_t sign_bit = ((*ptr & 0x80000000) >> 31);
	int32_t exponent = ((*ptr & 0x7f800000)>>23) - 127 - 23 + 10;//自行选择对齐的小数点位置
	uint32_t mantissa = (*ptr & 0x007fffff)+0x00800000;
	
	temp = (exponent>0)?(mantissa<<exponent):(mantissa>>-exponent);
	temp = (sign_bit)?-temp:temp;

	return temp ;
}

总结

你可能感兴趣的:(日常随机,开发语言,嵌入式,c语言)