计算机中的浮点数运算
创始人
2025-05-30 13:32:49

计算机中的浮点数

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

经典下溢场景

  不满足精度导致截断误差

#include 
#include 
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​=2a−b±b2−4ac​​
  由此设计程序

#include
#include
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 , -100000−0.00305176,−100000
  而保留小数点后六位有效数字应该是−0.001000,−99999.990000-0.001000,-99999.990000−0.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​=2a−b±b2−4ac​​
  分子分母同时乘以 −b−b2−4ac,−b+b2−4ac-b - \sqrt {b^2-4ac},-b + \sqrt {b^2-4ac}−b−b2−4ac​,−b+b2−4ac​ 可得
  $x_{1} = \frac{2c}{-b - \sqrt {b^2-4ac}} , x_{2} =\frac{2c}{-b + \sqrt {b^2-4ac}} $
  根据b 的正负性,两个求根公式各取一半得到新的算法
  新算法的结果为−0.001,−10000-0.001 , -10000−0.001,−10000

#include
#include
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;
}

相关内容

热门资讯

南向资金今日净卖出超45亿港元... 11月13日消息,南向资金今日净卖出45.51亿港元。港股通(沪)方面,盈富基金、恒生中国企业分别遭...
武汉凡谷:拟投资不超过1亿元参... 11月13日消息,武汉凡谷公告,为进一步丰富产业布局,实现可持续发展,公司有意向参与武汉光钜微电子有...
中远海控:斥资约2913万港元... 11月13日消息,中远海控(01919.HK)发布公告,当日斥资2913.28万港元回购股份250万...
宁夏前三季度已累计完成投资56... 11月13日消息,前三季度,宁夏累计完成固定资产投资1613亿元,其中100个重点建设项目已开复工9...