You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何计算表达式的相对与绝对精度?对比float与double并选型适配公差

关于浮点类型精度的三个问题解答

1. 如何计算指定类型表达式的相对精度与绝对精度?

要计算表达式的绝对精度和相对精度,核心是拿计算值真实参考值做对比,步骤大概是这样:

  • 第一步:先确定表达式的「真实值」——用比目标类型精度更高的类型(比如要算float的精度,就用long double来计算表达式的准确结果)作为参考基准,因为更高精度的类型能最大限度减少自身误差,接近数学上的真实结果。
  • 第二步:用目标类型(比如float/double)计算表达式的「实际计算值」。
  • 第三步:计算绝对误差|计算值 - 真实值|,这个值直接反映计算结果和真实值的绝对差距,就是绝对精度的量化指标。
  • 第四步:计算相对误差:如果真实值不等于0,就用绝对误差 / |真实值|,这个值是误差相对于真实值的比例,更适合衡量大数的精度。如果真实值接近0,相对误差会失去意义,这时候只看绝对误差就好。

举个简单例子:比如用float计算(1000000 + 1)/2,真实值是500000.5,float计算出来可能是500000,那绝对误差就是0.5,相对误差就是0.5 / 500000.5 ≈ 1e-6

2. 对比float与double类型时,表达式(x+y)/k的相对精度与绝对精度?

先得明确float和double的基础差异:float是单精度32位浮点型,尾数占23位,有效数字大概6-7位;double是双精度64位,尾数占52位,有效数字大概15-17位。两者的机器epsilon(能表示的最小相对误差)分别是1.19e-7(float)和2.22e-16(double)。

回到表达式(x+y)/k,误差主要来自两个环节:

  1. x+y的加法误差:如果x和y的数值差距很大(比如x是1e6,y是1),float会出现「大数吃小数」的情况——y的数值会被x的精度覆盖,加出来的结果还是x;但double因为尾数位数多,能保留y的有效信息,加法误差极小。
  2. 除以k的误差:除法的相对误差大概是机器epsilon的量级,double的这个值远小于float。

对比两者的精度:

  • 绝对精度:double的绝对误差普遍远小于float。比如刚才的例子,float算出来绝对误差0.5,double算出来几乎是0。即使是普通数值,double能表示的小数位数更多,绝对差距更小。
  • 相对精度:double的相对误差上限(1e-16)比float(1e-7)小几个数量级,所以不管是加法还是除法,double的相对精度都碾压float。比如计算很大的数时,float的相对误差可能到1e-6级别,而double的相对误差几乎可以忽略不计。

3. 哪种类型能满足表达式的相对公差1e-05、绝对公差1e-08?

先拆解两个公差的要求:

  • 相对公差1e-05:要求计算结果的相对误差≤1e-5;
  • 绝对公差1e-08:要求计算结果的绝对误差≤1e-08。

先看float:
float的机器epsilon是~1.19e-7,远小于1e-5,哪怕是多次运算累积误差,也很难超过1e-5的相对公差。对于绝对公差,当计算结果的绝对值比较大时(比如≥1e-3),相对误差1e-5对应的绝对误差是1e-5 * |结果|,这时候可能会超过1e-08,但此时相对误差满足要求;当结果绝对值很小(比如<1e-3),float的绝对误差会远小于1e-08(比如结果是1e-4,绝对误差大概是1e-4 * 1e-7=1e-11),完全符合绝对公差。

再看double:
double的精度比float高得多,自然也能轻松满足这两个公差要求,甚至有很大的余量,适合更复杂的运算场景或者对精度要求更高的后续处理。

总结:float已经能满足这两个公差要求,如果只是针对这个简单表达式,用float足够;但如果你的场景还有其他复杂运算、更大的数值范围或者需要更高的冗余精度,double会是更稳妥的选择。


内容的提问来源于stack exchange,提问作者Yas

火山引擎 最新活动