用查找表方式在MCU上实现对数运算

缘起

在MCU(Micro Control Unit)编程中,因为其处理能力有限,对浮点数的支持性能也一般,但有时我们希望在MCU上实现一些数学运算,比如固定长度FFT,比如对数运算,等等。这种情况下,如果直接使用math数学函数库,会带来巨大的性能影响。为此,可以采用空间换时间的方式,通过使用查找表(Look-Up-Table),在满足计算精度的要求下,实现快速的运算。本文就通过查找表的方式,探讨一种针对单精度浮点数的快速对数运算的方法。

单精度浮点数的表示

在计算机上,单精度浮点数是一个32位数字,包含1个符号位,8个指数位,和23个尾数位,如下图所示:
单精度浮点数表示
对于对数运算来说,数字必须为正,所以这里sign必须是1。对上述浮点数进行对数(log10)运算,我们得到:

log10(num) = (E - 127) x log10(2) + log10(1.b22b21...b0)

其中,等式右边的第一部分为普通的乘法运算(E = b30b29...b23),第二部分是针对尾数部分的对数运算,是我们讨论的重点。

计算精度及查表法实现

在进一步讨论查表法实现的方法之前,先探讨计算机进行对数运算的精度问题。我们来看如下的函数公式:

y = lg(x) = ln(x) / ln(10)

其中lg表示以10为底的对数运算,ln表示以e为底的对数运算(自然对数)。那么我们得到y的微分如下:

dy = (1 / (x ln(10)) dx = dx / x / ln(10)

也就是说,数值计算的精度(dy),与x的大小成反比,x越大,计算误差dy越小。对于上一节提到的单精度浮点数计算公式来说,计算精度主要取决于第二部分对尾数部分的运算。由于尾数部分取值在[1, 2)区间内,即1 <= x < 2,计算误差最大的位置在当x == 1时。为此,若只考虑最大计算误差,我们可以简化误差计算公式为:

dy = dx / 1 / ln(10) = dx / ln(10)

对于完整的尾数部分,其数值表达精度为1 / 2^23 = 0.00000011920929 = 1.1920929 * 10e-7,因此计算误差(假设计算过程不引入新的误差)为1.7198265 * 10e-7

但是,在实际应用中,我们可能并不需要这么高的精度。例如,如果对数计算结果是用来表示信号的功率的分贝(dB)值,那么0.01dB就是一个不错的精度了。假设我们的目标精度是0.01dB,我们看看具体是什么情况。根据dB计算的公式,假设信号功率为x,那么转换成dB的公式为:

z = 20 * log10(x) = 20 lg(x)

那么dz = 20 dy = dx * 20 / ln(10),假设dz = 0.01,那么dx = dz * ln(10) / 20 = 0.00115,也就是说,只要x的精度好于0.00115,我们就可以达到0.01dB的精度。我们来看看用几位尾数精度可以达到0.00115的精度:

尾数比特数 精度 分数表示精度
1 0.5 1/2
2 0.25 1/4
3 0.125 1/8
4 0.0625 1/16
5 0.03125 1/32
6 0.015625 1/64
7 0.0078125 1/128
8 0.00390625 1/256
9 0.001953125 1/512
10 0.0009765625 1/1024
11 0.00048828125 1/2048
12 0.000244140625 1/4096
13 0.0001220703125 1/8192

从表中我们可以看到,当尾数比特数为10时,其精度达到了0.0009765625,好于0.01dB所要求的尾数精度0.00115。所以,我们可以取10比特尾数表示单精度浮点数,并构建一个1024(2^10)个表项的查找表来实现该对数运算:

/** Log Table for [1, 2), with step 0.0009765625 */
const float Log10Table[1024] = {
   
    0, 0.000423909, 0.000847404, 0.00127049, 0.00169316, 0.00211542, 0.00253727, 0.00295871,
    0.00337974, 0.00380036, 0.00422058, 0.00464039, 0.0050598, 0.0054788, 0.0058974, 0.00631559,
    0.00673338, 0.00715077, 0.00756776, 0.00798435, 0.00840054, 0.00881633, 0.00923173, 0.00964672,
    0.0100613, 0.0104755, 0.0108893, 0.0113028, 0.0117158, 0.0121284, 0.0125407, 0.0129525,
    0.013364, 0.013775, 0.0141857, 0.014596, 0.0150059, 0.0154154, 0.0158246, 0.0162333,
    0.0166417, 0.0170497, 0.0174572, 0.0178645, 0.0182713, 0.0186777, 0.0190838, 0.0194895,
    0.0198948, 0.0202998, 0.0207043, 0.0211085, 0.0215123, 0.0219157, 0.0223188, 0.0227215,
    0.0231238, 0.0235257, 0.0239273, 0.0243285, 0.0247293, 0.0251298, 0.0255299, 0.0259296,
    0.0263289, 0.0267279, 0.0271265, 0.0275248, 0.0279227, 0.0283202, 0.0287174, 0.0291142,
    0.0295106, 0.0299067, 0.0303024, 0.0306977, 0.0310927, 0.0314874, 0.0318816, 0.0322756,
    0.0326691, 0.0330623, 0.0334552, 0.0338477, 0.0342398, 0.0346316, 0.035023, 0.0354141,
    0.0358048, 0.0361952, 0.0365852, 0.0369749, 0.0373642, 0.0377532, 0.0381418, 0.0385301,
    0.0389181, 0.0393057, 0.0396929, 0.0400798, 0.0404664, 0.0408526, 0.0412384, 0.041624,
    0.0420091, 0.042394, 0.0427785, 0.0431626, 0.0435465, 0.04393, 0.0443131, 0.0446959,
    0.0450784, 0.0454605, 0.0458423, 0.0462238, 0.0466049, 0.0469857, 0.0473661, 0.0477463,
    0.0481261, 0.0485055, 0.0488847, 0.0492635, 0.0496419, 0.0500201, 0.0503979, 0.0507754,
    0.0511525, 0.0515294, 0.0519059, 0.052282, 0.0526579, 0.0530334, 0.0534086, 0.0537835,
    0.054158, 0.0545323, 0.0549062, 0.0552798, 0.055653, 0.056026, 0.0563986, 0.0567709,
    0.0571429, 0.0575146, 0.0578859, 0.0582569, 0.0586277, 0.0589981, 0.0593681, 0.0597379,
    0.0601074, 0.0604765, 0.0608453, 0.0612138, 0.0615821, 0.0619499, 0.0623175, 0.0626848,
    0.0630517, 0.0634184, 0.0637847, 0.0641508, 0.0645165, 0.0648819, 0.065247, 0.0656118,
    0.0659763, 0.0663405, 0.0667044, 0.067068, 0.0674312, 0.0677942, 0.0681569, 0.0685192,
    0.0688813, 0.0692431, 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
MCU(Microcontroller Unit,微控制器单元)如何实现数据查找索引,取决于具体的MCU和应用场景。 一种常见的实现方式是使用哈希(Hash Table),它能够通过将数据转化为唯一的哈希值,并将哈希值与存储地址建立映射关系,从而快速定位数据。在MCU中,可以使用哈希函数将要查找的数据转化为一个索引,在MCU的存储空间中,每个索引对应着一个存储位置,数据存储在相应位置上。通过对数据进行哈希函数运算MCU可以快速查找到数据所对应的存储位置,实现高效的数据查找。 另一种实现方式是使用二叉搜索树(Binary Search Tree),它是一种有序树结构,每个节点的左子树的值均小于父节点的值,右子树的值均大于父节点的值。通过构建二叉搜索树,在MCU的存储空间中,每个节点存储着一个数据,同时保持左右子树的有序性,并通过比较的方式逐级定位要查找的数据。通过二叉搜索树的性质,MCU可以在平均情况下实现较快的数据查找。 此外,MCU还可以借助外部存储器,如闪存、SD卡等,利用其较大的存储空间来实现数据索引。MCU将索引数据存储在内部存储器中,并通过索引来标识外部存储器中的数据位置,从而实现数据的快速查找。 总体来说,MCU实现数据查找索引的方式取决于具体的应用场景和资源限制。无论是使用哈希、二叉搜索树还是外部存储器,都旨在提高数据查找的效率和准确性,以满足MCU在各种嵌入式应用中对数据处理和存储的需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值