当前位置: 首页 > news >正文

模拟32位浮点数的定义,加,减,显示。

本文介绍了一个32位浮点数模拟实现,使用C语言结构体封装了IEEE 754浮点数的三个组成部分:符号位(1位)、指数位(8位)和尾数位(23位)。通过定义Float32Ops结构体,实现了浮点数的设置、获取、加减运算和打印功能。核心算法包括浮点数规范化处理、指数对齐和尾数运算,支持特殊值(如零值)处理。演示程序验证了基本设置、加减运算等功能,展示了浮点数的二进制表示与十进制值的转换关系。该实现可用于理解浮点数运算原理或进行低精度浮点模拟。

#include <stdio.h>
#include <stdint.h>
#include <math.h>// 32位浮点数结构体
typedef struct {uint32_t sign : 1;      // 符号位 (1位)uint32_t exponent : 8;  // 指数位 (8位)uint32_t fraction : 23; // 尾数位 (23位)
} Float32;// 浮点数操作结构体
typedef struct {Float32 value;// 设置浮点数值void (*set)(struct Float32Ops*, float);// 获取浮点数值float (*get)(struct Float32Ops*);// 加法void (*add)(struct Float32Ops*, struct Float32Ops*);// 减法void (*sub)(struct Float32Ops*, struct Float32Ops*);// 打印浮点数信息void (*print)(struct Float32Ops*);
} Float32Ops;// 工具函数:将float转换为Float32
Float32 float_to_float32(float f) {Float32 result;uint32_t bits = *(uint32_t*)&f;result.sign = (bits >> 31) & 0x1;result.exponent = (bits >> 23) & 0xFF;result.fraction = bits & 0x7FFFFF;return result;
}// 工具函数:将Float32转换为float
float float32_to_float(Float32 f32) {uint32_t bits = (f32.sign << 31) | (f32.exponent << 23) | f32.fraction;return *(float*)&bits;
}// 设置浮点数值
void set_float(Float32Ops* ops, float value) {ops->value = float_to_float32(value);
}// 获取浮点数值
float get_float(Float32Ops* ops) {return float32_to_float(ops->value);
}// 打印浮点数详细信息
void print_float(Float32Ops* ops) {float actual_value = get_float(ops);printf("符号位: %d\n", ops->value.sign);printf("指数位: %d (0x%02X)\n", ops->value.exponent, ops->value.exponent);printf("尾数位: %d (0x%06X)\n", ops->value.fraction, ops->value.fraction);printf("实际值: %f\n", actual_value);printf("十六进制: 0x%08X\n\n", *(uint32_t*)&actual_value);
}// 规范化浮点数
void normalize(Float32* result) {if (result->fraction == 0) {// 零值result->exponent = 0;result->sign = 0;return;}// 找到最高位的1uint32_t fraction = result->fraction;int shift = 0;while (!(fraction & 0x400000)) { // 检查第23位(隐藏位的位置)fraction <<= 1;shift++;}if (shift > 0) {result->fraction = fraction & 0x7FFFFF;result->exponent -= shift;}// 处理上溢和下溢if (result->exponent >= 0xFF) {// 上溢,设置为无穷大result->exponent = 0xFF;result->fraction = 0;} else if (result->exponent == 0) {// 下溢,设置为0result->sign = 0;result->fraction = 0;}
}// 浮点数加法
void add_floats(Float32Ops* a, Float32Ops* b) {Float32 result;Float32 f1 = a->value;Float32 f2 = b->value;// 处理特殊情况:零值if (f1.exponent == 0 && f1.fraction == 0) {a->value = f2;return;}if (f2.exponent == 0 && f2.fraction == 0) {return; // a保持不变}// 提取实际的指数和尾数(包括隐藏位)int32_t exp1 = (f1.exponent == 0) ? -126 : (int32_t)f1.exponent - 127;int32_t exp2 = (f2.exponent == 0) ? -126 : (int32_t)f2.exponent - 127;uint32_t mant1 = (f1.exponent == 0) ? f1.fraction : (f1.fraction | 0x800000);uint32_t mant2 = (f2.exponent == 0) ? f2.fraction : (f2.fraction | 0x800000);// 对齐指数int32_t exp_diff = exp1 - exp2;if (exp_diff > 0) {mant2 >>= exp_diff;exp2 = exp1;} else if (exp_diff < 0) {mant1 >>= (-exp_diff);exp1 = exp2;}// 执行加法uint32_t result_mant;uint8_t result_sign;if (f1.sign == f2.sign) {// 同号相加result_mant = mant1 + mant2;result_sign = f1.sign;} else {// 异号相减if (mant1 >= mant2) {result_mant = mant1 - mant2;result_sign = f1.sign;} else {result_mant = mant2 - mant1;result_sign = f2.sign;}}// 构建结果result.sign = result_sign;if (result_mant == 0) {// 结果为0result.exponent = 0;result.fraction = 0;} else {// 规范化结果while (result_mant > 0xFFFFFF) {result_mant >>= 1;exp1++;}while ((result_mant & 0x800000) == 0) {result_mant <<= 1;exp1--;}result.exponent = (exp1 + 127) & 0xFF;result.fraction = result_mant & 0x7FFFFF;}a->value = result;
}// 浮点数减法
void sub_floats(Float32Ops* a, Float32Ops* b) {// 减法就是加上相反数Float32Ops temp = *b;temp.value.sign = !temp.value.sign; // 改变符号add_floats(a, &temp);
}// 初始化浮点数操作结构体
void init_float32(Float32Ops* f) {f->set = set_float;f->get = get_float;f->add = add_floats;f->sub = sub_floats;f->print = print_float;// 初始化为0f->value.sign = 0;f->value.exponent = 0;f->value.fraction = 0;
}// 演示程序
int main() {printf("=== 32位浮点数模拟演示 ===\n\n");Float32Ops a, b, c;init_float32(&a);init_float32(&b);init_float32(&c);// 测试基本设置和读取printf("1. 基本设置和读取测试:\n");a.set(&a, 3.14f);printf("设置 a = 3.14:\n");a.print(&a);b.set(&b, 2.71f);printf("设置 b = 2.71:\n");b.print(&b);// 测试加法printf("2. 加法测试:\n");c.set(&c, 3.14f);c.add(&c, &b);printf("3.14 + 2.71 = %f\n", c.get(&c));printf("实际值应该是: 5.85\n\n");// 测试减法printf("3. 减法测试:\n");c.set(&c, 10.5f);c.sub(&c, &b);printf("10.5 - 2.71 = %f\n", c.get(&c));printf("实际值应该是: 7.79\n\n");// 测试负数printf("4. 负数测试:\n");a.set(&a, -5.5f);b.set(&b, 3.25f);c.set(&c, -5.5f);c.add(&c, &b);printf("-5.5 + 3.25 = %f\n", c.get(&c));printf("实际值应该是: -2.25\n\n");// 测试边界情况printf("5. 边界情况测试:\n");a.set(&a, 0.0f);printf("零值:\n");a.print(&a);a.set(&a, 1.0f);b.set(&b, -1.0f);c.set(&c, 1.0f);c.add(&c, &b);printf("1.0 + (-1.0) = %f\n", c.get(&c));return 0;
}

这里是引用

http://www.dtcms.com/a/532128.html

相关文章:

  • GitHub等平台形成的开源文化正在重塑家庭日
  • leetcode 228. 汇总区间 python
  • C# List集合
  • F280025的时钟设置
  • PBR太“脏”,手绘太“平”?Substance“风格化PBR”工作流才是版本答案
  • 建设部执业资格注册中心网站logo一键生成器免费版原型图
  • tcpdump 常用命令及参数解析
  • 调用 Google Veo 3.1 API 批量制作电商产品 UGC 视频
  • 网站链接怎么做二维码wordpress支持 nginx
  • 首次使用Gitlab创建项目的详细操作流程
  • 音视频格式转换API接口使用指南
  • 怎么用壳域名做网站wordpress添加形式
  • 网站做视频郑州作网站
  • 【机器学习】Scikit-learn 框架基础
  • [人工智能-大模型-85]:大模型应用层 - AI/AR眼镜:华为智能眼镜、苹果智能眼镜、Google Glass智能眼镜的软硬件技术架构
  • Windows下利用boost库与Windows Api 实现共享内存
  • 绵阳网站建设优化如何做网站的书籍
  • RedisFX Maven 使用教程
  • Python + ADB 手机自动化控制教程
  • MATLAB三维电容仿真与分析
  • Hadoop安全模式详解
  • .NET 任务 Task、Task.Run()、 Task.WhenAll()、Task.WhenAny()
  • 英文营销网站建设南京成旭通网站建设公司怎么样
  • wordpress如何做站群关键词优化易下拉效率
  • 面试官问 Linux 编译调试?gcc 编译流程 + gdb 断点调试 + git 版本控制,连 Makefile 都标好了
  • C语言练习题(二)
  • 【QSS】软件界面的美工操作——Qt 界面优化
  • 网页版html编辑器手机优化大师
  • 【思想比实现更重要】高并发场景下如何保证接口幂等性
  • Spring Expression Language (SpEL) 详解:功能强大的表达式引擎