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

计算机中的浮点数运算

计算机中的浮点数

  计算机中以固定长度存储浮点数的方式,造成了浮点数运算过程容易产生上溢和下溢。以float32为例, 其标记位占1bit,指数位占8bit,小数部分占23bit
在这里插入图片描述

经典下溢场景

  不满足精度导致截断误差

#include <iostream>
#include <iomanip>
using namespace std;
int main() {float a = 1.f;float eps = 1e-8f;float c = a + eps;cout << setprecision(16) << a << "+" << eps << "=" << c << endl;return 0;
}

微小的误差很容易被放大

  这里以二元一次方程的求根为例
  ax2+bx+c=0ax^{2}+bx+c=0ax2+bx+c=0
  根据基础数学知识,你会给出这样一个解决方案
  x1,2=−b±b2−4ac2ax_{1,2} = \frac{-b\pm \sqrt {b^2-4ac}}{2a}x1,2=2ab±b24ac
  由此设计程序

#include<iostream>
#include<cmath>
using namespace std;int main() {float a, b, c;float temp, root, r1, r2;cout << "该程序用于求一元二次方程ax^2+bx+c=0的解" << endl;cout << "请依次输入a b c的值(a不要为0)" << endl;cin >> a >> b >> c;temp = b * b - 4 * a * c;root = sqrt(temp);if (temp < 0) {cout << "改方程无解\n";return -1;}r1 = (-b + root) / 2.0 / a;r2 = (-b - root) / 2.0 / a;cout << "一元二次方程的解为:" << r1 << " , " << r2 << endl;return 0;
}

  使用这段程序输入 0.01,1000,10.01,1000,10.01,1000,1
  输出−0.00305176,−100000-0.00305176 , -1000000.00305176,100000
  而保留小数点后六位有效数字应该是−0.001000,−99999.990000-0.001000,-99999.9900000.001000,99999.990000
  此时,第一项的相对误差为百分之两百,而第二项的相对误差为千万分之一。
  显然,两个相近的数相减会使得运算后的有效位数变少,也就是在a,ca,ca,c的值很小时, $ -b + \sqrt {b^2-4ac}$ 这一操作过后,使得实际结果的有效位变低了(或者说引入了较大的误差),并且这个误差会在后续的运算中被放大。
  这时可以通过数学手段减少误差
  既然 x1,2=−b±b2−4ac2ax_{1,2} = \frac{-b\pm \sqrt {b^2-4ac}}{2a}x1,2=2ab±b24ac
  分子分母同时乘以 −b−b2−4ac,−b+b2−4ac-b - \sqrt {b^2-4ac},-b + \sqrt {b^2-4ac}bb24ac,b+b24ac 可得
  $x_{1} = \frac{2c}{-b - \sqrt {b^2-4ac}} , x_{2} =\frac{2c}{-b + \sqrt {b^2-4ac}} $
  根据b 的正负性,两个求根公式各取一半得到新的算法
  新算法的结果为−0.001,−10000-0.001 , -100000.001,10000

#include<iostream>
#include<cmath>
using namespace std;int main() {float a, b, c;float temp, root, r1, r2;cout << "该程序用于求一元二次方程ax^2+bx+c=0的解" << endl;cout << "请依次输入a b c的值(a不要为0)" << endl;cin >> a >> b >> c;temp = b * b - 4 * a * c;root = sqrt(temp);if (temp < 0) {cout << "改方程无解\n";return -1;}if (b > 0) {r1 = 2 * c / (-b - root);r2 = (-b - root) / 2 / a;}else if (b < 0) {r1 = (-b + root) / 2 / a;r2 = 2 * c / (-b + root);}else {temp = c / a;r1 = sqrt(-temp);r2 = -sqrt(-temp);}cout << "一元二次方程的解为:" << r1 << " , " << r2 << endl;return 0;
}
http://www.lryc.cn/news/40852.html

相关文章:

  • 看了字节跳动月薪20K+测试岗面试题,让我这个工作3年的测试工程师,冷汗直流....
  • 这两天最好的ChatGPT应用;使用Notion AI提升效率的经验(13);AI编程与程序员的生存 | ShowMeAI日报
  • Linux 内核likely与unlikey
  • 成功解决主从同步异常之Slave_IO_Running显示为No的问题
  • 面试阿里测开岗失败后,被面试官在朋友圈吐槽了......
  • 蓝桥杯嵌入式--字符串比较在串口通信中的应用
  • 考研408每周一题(2019 41)
  • Angular学习笔记(一)
  • Linux用户和权限 —— 操作演示
  • 【华为OD机试真题2023 JAVA】单核CPU任务调度
  • News乐鑫科技亮相德国嵌入式展 Embedded World 2023!
  • java如何创建线程
  • 要是早看到这篇文章,你起码少走3年弯路,20年老程序员的忠告
  • IP地址的分类
  • win10下使用docker运行部署nginx,mysql
  • sprinboot车辆充电桩
  • 仿京东放大镜效果的实现
  • ESP32设备驱动-LM35温度传感器驱动
  • 基于深度学习的犬种识别软件(YOLOv5清新界面版,Python代码)
  • 【IDEA插件开发】环境搭建
  • 【蓝桥杯专题】 DP(C++ | 洛谷 | acwing | 蓝桥)
  • 咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包
  • 重构数据-Change Value to Reference将实值对象改为引用对象三
  • 计算机网络——通信专业面试问题学习笔记
  • 代码随想录算法训练营第三十天 | 332.重新安排行程 51. N皇后 37. 解数独 总结
  • Windows权限提升—MySQL数据库提权
  • 使用旧电脑玩Linux
  • Linux安装EMQX(简洁版)
  • 基于STM32 + FPGA 的软体机器人的 CAN总线运动控制器的设计
  • ROC曲线和AUC值