目录

一、原理介绍        

二、代码实现

三、结果显示

四、移植到C语言中的应用

4.1. 定义定点数配置和参数

4.2. 实现分段查找函数

4.3. 实现 log10 近似计算函数

4.4. (可选)定点数转浮点数


一、原理介绍        

        之前的博文对数函数分段线性实现讲解了理论方法和误差分析。这篇博文讲解其定点实现方法。

二、代码实现

import math# 定点数配置
FRACTIONAL_BITS = 16  # 小数部分位数
INTEGER_BITS = 32 - FRACTIONAL_BITS  # 整数部分位数
SCALE_FACTOR = 1 << FRACTIONAL_BITS  # 2^16 = 65536def generate_segment_points():"""生成所有分段点"""points = [0, 1, 2, 3, 4, 5, 6, 7]# 后续以2的指数为点,直到不超过4095exp = 3  # 2^3 = 8,接续7之后while True:point = 2 ** expif point > 4095:breakpoints.append(point)exp += 1# 确保最后一个点是4095if points[-1] < 4095:points.append(4095)return pointsdef float_to_fixed(value):"""将浮点数转换为定点数表示"""# 计算最大值和最小值max_val = (1 << INTEGER_BITS) - (1.0 / SCALE_FACTOR)min_val = -(1 << INTEGER_BITS)# 截断到范围内if value > max_val:value = max_valelif value < min_val:value = min_val# 转换为定点数fixed_point = int(round(value * SCALE_FACTOR))# 确保在32位有符号整数范围内if fixed_point > 0x7FFFFFFF:fixed_point = 0x7FFFFFFFelif fixed_point < -0x80000000:fixed_point = -0x80000000return fixed_pointdef fixed_to_float(fixed_value):"""将定点数转换回浮点数"""return fixed_value / SCALE_FACTORdef calculate_segments(points):"""计算每段的斜率和截距(浮点和定点)"""segments = []for i in range(len(points) - 1):x1 = points[i]x2 = points[i + 1]# 处理x=0的特殊情况(log10(0)无定义,用log10(1)代替)if x1 == 0:y1 = math.log10(1)  # log10(1) = 0else:y1 = math.log10(x1)y2 = math.log10(x2)# 计算斜率和截距(浮点)if x2 == x1:k_float = 0.0else:k_float = (y2 - y1) / (x2 - x1)b_float = y1 - k_float * x1# 转换为定点数k_fixed = float_to_fixed(k_float)b_fixed = float_to_fixed(b_float)# 还原定点数为浮点数,用于对比k_fixed_float = fixed_to_float(k_fixed)b_fixed_float = fixed_to_float(b_fixed)segments.append({'segment_id': i,'start': x1,'end': x2,# 浮点参数'k_float': k_float,'b_float': b_float,# 定点参数(整数表示)'k_fixed': k_fixed,'b_fixed': b_fixed,# 定点参数还原为浮点(用于精度参考)'k_fixed_float': k_fixed_float,'b_fixed_float': b_fixed_float})return segmentsdef main():# 生成分段点points = generate_segment_points()print(f"分段点: {points}")print(f"共{len(points)-1}段直线\n")# 计算分段参数segments = calculate_segments(points)# 输出定点数配置print("定点数配置:")print(f"总位数: 32位")print(f"整数部分: {INTEGER_BITS}位")print(f"小数部分: {FRACTIONAL_BITS}位")print(f"缩放因子: 2^{FRACTIONAL_BITS} = {SCALE_FACTOR}\n")# 显示斜率对比print("斜率(k)参数对比:")print(f"{'分段ID':<8} {'x范围':<12} {'浮点值':<18} {'定点整数值':<18} {'定点还原浮点值':<18}")print("-" * 80)for seg in segments:x_range = f"[{seg['start']}, {seg['end']}]"print(f"{seg['segment_id']:<8} {x_range:<12} {seg['k_float']:<18.10f} "f"{seg['k_fixed']:<18} {seg['k_fixed_float']:<18.10f}")# 显示截距对比print("\n截距(b)参数对比:")print(f"{'分段ID':<8} {'x范围':<12} {'浮点值':<18} {'定点整数值':<18} {'定点还原浮点值':<18}")print("-" * 80)for seg in segments:x_range = f"[{seg['start']}, {seg['end']}]"print(f"{seg['segment_id']:<8} {x_range:<12} {seg['b_float']:<18.10f} "f"{seg['b_fixed']:<18} {seg['b_fixed_float']:<18.10f}")# 生成嵌入式可用的C语言数组定义print("\n嵌入式C语言参数数组:")print("/* 分段点定义 */")print(f"const uint16_t segment_points[] = {{ {', '.join(map(str, points))} }};")print(f"const uint8_t num_segments = {len(segments)};\n")print("/* 斜率(k)定点数值组 */")k_values = [str(seg['k_fixed']) for seg in segments]print(f"const int32_t k_fixed[] = {{ {', '.join(k_values)} }};\n")print("/* 截距(b)定点数值组 */")b_values = [str(seg['b_fixed']) for seg in segments]print(f"const int32_t b_fixed[] = {{ {', '.join(b_values)} }};")if __name__ == "__main__":main()

三、结果显示

段点: [0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4095]
共17段直线定点数配置:
总位数: 32位
整数部分: 16位
小数部分: 16位
缩放因子: 2^16 = 65536斜率(k)参数对比:
分段ID     x范围          浮点值                定点整数值              定点还原浮点值           
--------------------------------------------------------------------------------
0        [0, 1]       0.0000000000       0                  0.0000000000      
1        [1, 2]       0.3010299957       19728              0.3010253906      
2        [2, 3]       0.1760912591       11540              0.1760864258      
3        [3, 4]       0.1249387366       8188               0.1249389648      
4        [4, 5]       0.0969100130       6351               0.0969085693      
5        [5, 6]       0.0791812460       5189               0.0791778564      
6        [6, 7]       0.0669467896       4387               0.0669403076      
7        [7, 8]       0.0579919470       3801               0.0579986572      
8        [8, 16]      0.0376287495       2466               0.0376281738      
9        [16, 32]     0.0188143747       1233               0.0188140869      
10       [32, 64]     0.0094071874       617                0.0094146729      
11       [64, 128]    0.0047035937       308                0.0046997070      
12       [128, 256]   0.0023517968       154                0.0023498535      
13       [256, 512]   0.0011758984       77                 0.0011749268      
14       [512, 1024]  0.0005879492       39                 0.0005950928      
15       [1024, 2048] 0.0002939746       19                 0.0002899170      
16       [2048, 4095] 0.0001470073       10                 0.0001525879      截距(b)参数对比:
分段ID     x范围          浮点值                定点整数值              定点还原浮点值           
--------------------------------------------------------------------------------
0        [0, 1]       0.0000000000       0                  0.0000000000      
1        [1, 2]       -0.3010299957      -19728             -0.3010253906     
2        [2, 3]       -0.0511525224      -3352              -0.0511474609     
3        [3, 4]       0.1023050449       6705               0.1023101807      
4        [4, 5]       0.2144199393       14052              0.2144165039      
5        [5, 6]       0.3030637741       19862              0.3030700684      
6        [6, 7]       0.3764705126       24672              0.3764648438      
7        [7, 8]       0.4391544112       28780              0.4391479492      
8        [8, 16]      0.6020599913       39457              0.6020660400      
9        [16, 32]     0.9030899870       59185              0.9030914307      
10       [32, 64]     1.2041199827       78913              1.2041168213      
11       [64, 128]    1.5051499783       98642              1.5051574707      
12       [128, 256]   1.8061799740       118370             1.8061828613      
13       [256, 512]   2.1072099696       138098             2.1072082520      
14       [512, 1024]  2.4082399653       157826             2.4082336426      
15       [1024, 2048] 2.7092699610       177555             2.7092742920      
16       [2048, 4095] 3.0102589912       197280             3.0102539062      嵌入式C语言参数数组:
/* 分段点定义 */
const uint16_t segment_points[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4095 };
const uint8_t num_segments = 17;/* 斜率(k)定点数值组 */
const int32_t k_fixed[] = { 0, 19728, 11540, 8188, 6351, 5189, 4387, 3801, 2466, 1233, 617, 308, 154, 77, 39, 19, 10 };/* 截距(b)定点数值组 */
const int32_t b_fixed[] = { 0, -19728, -3352, 6705, 14052, 19862, 24672, 28780, 39457, 59185, 78913, 98642, 118370, 138098, 157826, 177555, 197280 };

四、移植到C语言中的应用

4.1. 定义定点数配置和参数

首先在 C 文件中定义定点数配置(需与 Python 中一致)和从 Python 复制的参数:

#include <stdint.h>  // 用于uint16_t、int32_t等类型// 定点数配置(必须与Python代码中的设置一致)
#define FRACTIONAL_BITS 16  // 小数部分位数(与Python的FRACTIONAL_BITS相同)
#define SCALE_FACTOR (1 << FRACTIONAL_BITS)  // 2^16 = 65536// 从Python输出复制的分段参数
const uint16_t segment_points[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4095};
const uint8_t num_segments = sizeof(segment_points) / sizeof(segment_points[0]) - 1;const int32_t k_fixed[] = {28961,   // 第0段斜率(示例值,需替换为Python输出)13230,   // 第1段斜率// ... 其他分段的k值146      // 最后一段斜率
};const int32_t b_fixed[] = {0,       // 第0段截距(示例值,需替换为Python输出)-15731,  // 第1段截距// ... 其他分段的b值196602   // 最后一段截距
};
4.2. 实现分段查找函数

根据输入 x(0~4095),找到对应的分段索引(即使用哪组 k 和 b):

/*** 查找x所属的分段索引* 参数:x - 输入值(0~4095)* 返回:分段索引(0 ~ num_segments-1)*/
static uint8_t find_segment(uint16_t x) {// 遍历分段点,找到x所在的区间for (uint8_t i = 0; i < num_segments; i++) {if (x >= segment_points[i] && x <= segment_points[i + 1]) {return i;}}return num_segments - 1;  // 兜底(x=4095)
}
4.3. 实现 log10 近似计算函数

利用找到的分段参数(k 和 b),通过定点数运算计算 log10 (x) 的近似值:

/*** 计算log10(x)的近似值(定点数输出)* 参数:x - 输入值(0~4095,整数)* 返回:log10(x)的定点数表示(精度:FRACTIONAL_BITS位小数)*/
int32_t log10_approx(uint16_t x) {if (x == 0) {return 0;  // 特殊处理x=0(log10(0)无定义,返回0)}// 1. 查找x所属的分段uint8_t seg_idx = find_segment(x);  // 或使用find_segment_fast// 2. 取出该分段的k和b(定点数)int32_t k = k_fixed[seg_idx];int32_t b = b_fixed[seg_idx];// 3. 定点数运算:y = k * x + b(需处理小数位对齐)// x是整数,先转换为定点数(x << FRACTIONAL_BITS)int64_t x_fixed = (int64_t)x << FRACTIONAL_BITS;  // 扩展为64位避免乘法溢出// 计算k * x:结果小数位为FRACTIONAL_BITS*2,右移FRACTIONAL_BITS位对齐int64_t product = (k * x_fixed) >> FRACTIONAL_BITS;// 加上截距b(已为定点数,直接相加)int64_t y_fixed = product + b;// 4. 截断为32位(防止溢出)if (y_fixed > INT32_MAX) {return INT32_MAX;} else if (y_fixed < INT32_MIN) {return INT32_MIN;} else {return (int32_t)y_fixed;}
}
4.4. (可选)定点数转浮点数

若需要将结果转换为浮点数(如用于显示或上层计算):

/*** 将定点数结果转换为浮点数* 参数:fixed_val - log10_approx返回的定点数* 返回:对应的浮点数*/
float fixed_to_float(int32_t fixed_val) {return (float)fixed_val / SCALE_FACTOR;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918123.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918123.shtml
英文地址,请注明出处:http://en.pswp.cn/news/918123.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt系统--事件

文章目录qt系统事件处理鼠标事件鼠标移动事件处理键盘事件定时器事件窗口移动和大小改变事件结语很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 作者&#xff1a;٩( ‘ω’ )و260 我的专栏&#xff1a…

Linux机器可直接使用的自动化编译文件

还在为了Linux机器上一遍遍输入编译指令苦恼吗&#xff1f;你需要make指令以及自己的makefile文件&#xff01;在makefile中写入自己的个性化指令&#xff0c;让编译速度飞起&#xff0c;支持多文件编译一下文件为个人应用&#xff0c;可以直接cp到相应项目的目录&#xff0c;每…

Linux学习-数据结构(哈希表)

1.哈希表1.哈希算法将数据通过哈希算法映射成一个关键值&#xff0c;存放都在同一位置实现数据的高效存储和查找&#xff0c;将时间复杂度尽可能降低至O&#xff08;1&#xff09;2.哈希碰撞多个数据通过哈希算法得到的键值相同&#xff0c;称为产生哈希碰撞3.哈希表构建哈希表…

Google Chrome <139.0.7236.0 UAF漏洞

【高危】Google Chrome <139.0.7236.0 UAF漏洞 漏洞描述 Google Chrome 是美国谷歌&#xff08;Google&#xff09;公司的一款Web浏览器。 受影响版本中&#xff0c;OpenscreenSessionHost::ReportAndLogError 方法的参数使用了 std::string_view 类型来接收错误消息。当一…

CentOS8 Stream 网卡配置及重启

在 CentOS 8 Stream 中&#xff0c;网卡配置已由 NetworkManager 管理&#xff0c;传统的 ifcfg-eth0 文件仍然支持&#xff0c;但推荐使用 nmcli 或 nmtui 工具进行网络配置和管理。以下是网卡配置及重启的详细步骤&#xff1a;1. 查看当前网卡状态列出所有网卡bash复制nmcli …

SpringMvc的原理深度剖析及源码解读

一、springmvc启动加载流程1、引入spring-web.jar包时&#xff0c;在这个包的META-INF/services/javax.servlet.ServletContainerInitializer文件中定义的加载类SpringServletContainerInitializer,提供给springmvc实现初始化的操作。2、在SpringServletContainerInitializer类…

【ESP32-menuconfig(1) -- Build Type及Bootloader config】

Build Type Bootloader configmenuconfig介绍Build typeCONFIG_APP_BUILD_TYPECONFIG_APP_BUILD_TYPE_PURE_RAM_APPCONFIG_APP_REPRODUCIBLE_BUILDCONFIG_APP_NO_BLOBSCONFIG_APP_COMPATIBLE_PRE_V2_1_BOOTLOADERSCONFIG_APP_COMPATIBLE_PRE_V3_1_BOOTLOADERSBootloader config…

C++信息学奥赛一本通-第一部分-基础一-第3章-第1节

C信息学奥赛一本通-第一部分-基础一-第3章-第1节 2051 偶数 #include <iostream>using namespace std;int main() {int number; cin >> number;if (number % 2 0) {cout << "yes";} }2052 范围判断 #include <iostream>using namespace std…

自由学习记录(79)

PBRBRDF原理&Unity实现深入浅出_哔哩哔哩_bilibili 进行改进 一个像素点对应一个范围内的 一个微表面--一个由无数个起起伏伏的结构组成的物理结构 屏幕上的每一个像素点&#xff0c;在渲染时通常会被视为一个“微表面”的代表 比如在这个图中&#xff0c;只关心红色的区…

复杂路况误报率↓78%!陌讯轻量化模型在车辆违停识别的边缘计算优化​

一、行业痛点&#xff1a;动态交通场景的识别困境据《2024中国智慧交通白皮书》统计&#xff0c;城市核心路段违停误报率高达35%&#xff0c;主要源于两大难点&#xff1a;​​短暂停靠干扰​​&#xff1a;出租车临时停靠与违停行为特征重叠​​复杂背景干扰​​&#xff1a;树…

大语言模型提示工程与应用:提示词基础使用方式

提示词使用方式 学习目标 在本课程中&#xff0c;我们将学习更多关于提示词使用方式。 相关知识点 提示词使用 学习内容 1 提示词使用 1.1 文本摘要 语言模型最典型的应用场景之一就是文本摘要。我们可以通过以下提示实现基础摘要功能&#xff1a; 提示: 解释抗生素是什么回答&…

常见命令-资源查看-iostat命令实践

文章目录 系统中未安装 iostat 命令 1. 监控CPU与磁盘的基础负载 2. 诊断I/O性能瓶颈 3. 实时监控与动态采样 4. 特定设备或分区的精细化监控 5. 性能测试与基准数据生成 6. 结合其他工具进行综合调优 总结 结果输出速查表 第一部分:CPU统计信息 第二部分:设备/磁盘统计信息(…

WinForm 实战 (进度条):用 ProgressBar+Timer 打造动态进度展示功能

目录 核心控件解析​ ProgressBar 进度条​ Timer 定时器​ 实战案例 常见应用场景​ 总结​ 在 WinForm 桌面应用开发中&#xff0c;进度反馈是提升用户体验的关键环节。无论是文件处理、数据加载还是复杂计算&#xff0c;一个直观的进度条能让用户清晰了解任务状态&…

使用 ast-grep 精准匹配指定类的方法调用(以 Java 为例)

使用 ast-grep 精准匹配指定类的方法调用&#xff08;以 Java 为例&#xff09; 在代码重构、安全审计或静态分析的场景中&#xff0c;我们常常需要匹配某个特定类中定义的方法调用。而 ast-grep 作为一款基于语法树的代码搜索工具&#xff0c;提供了强大的模式匹配功能&#…

Dijkstra?spfa?SPstra?

带负权的无负环最短路问题 对于一张有负边权的图&#xff0c;普通 Dijkstra 就不能用了&#xff0c;比如&#xff1a;正常的 Dijkstra 扩散的节点依次为 1,3,2,41,3,2,41,3,2,4。 这时候可以发现&#xff0c;当点 222 扩散的时候&#xff0c;原本达到点 333 的路径长度是 111&a…

React函数组件灵魂搭档:useEffect深度通关指南!

你以为它只是替代componentDidMount&#xff1f;数据抓取、事件绑定、定时清理...&#xff1f;事实上&#xff0c;useEffect才是函数组件的“幕后操控者”&#xff01;但依赖数组的坑、闭包的陷阱&#xff0c;你真的玩转了吗&#xff1f; 告别“能用就行”&#xff0c;今天带你…

LabVIEW实验室测试框架

在实验室测试场景中&#xff0c;选用合适的 LabVIEW 框架能够极大提升测试效率、优化测试流程并保障测试结果的准确性。介绍几款常用且功能强大的 LabVIEW 测试框架&#xff1a;​TestStand​框架概述​TestStand 是 NI 公司专为测试系统开发设计的一款测试执行管理框架。它能够…

Kiro :从“规范”到“实现”的全流程 AI 助手

为什么是 Kiro Kiro 是一款面向“规范驱动开发”&#xff08;Spec-Driven Development&#xff09;的 AI 开发助手。与只在“写代码”环节辅助不同&#xff0c;Kiro 将“从需求到设计再到实现”的完整链路显性化&#xff0c;把需求、设计、任务分解、代码与测试、文档等全部纳…

【0基础PS】PS工具详解--矩形工具

目录前言一、矩形工具的基础认知​二、矩形工具的选项栏详解​三、矩形工具的绘制技巧​四、矩形工具的实际应用场景​五、常见问题与解决方案​总结前言 在 Photoshop&#xff08;简称 PS&#xff09;的众多绘图工具中&#xff0c;矩形工具是使用率极高的基础工具之一。无论是…

移动端app专项测试

学习目标&#xff1a;app专项测试知识点&#xff0c;其他知识扩充一、app专项&#xff08;app怎么测试/app侧重点在哪&#xff09;1.功能&#xff1a;跟前面功能测试一样&#xff08;跟需求文档提取测试点&#xff0c;编写测试用例&#xff09;2.安装1.不同品牌安装,不同操作系…