C 预划分分母时,数值不稳定的风险是什么?
假设我想把一个数字分成许多C 预划分分母时,数值不稳定的风险是什么?,c,floating-point,numeric,ieee-754,C,Floating Point,Numeric,Ieee 754,假设我想把一个数字分成许多 a /= x; b /= x; c /= x; ... 因为乘法运算速度更快,所以我们很想这样做 tmp = 1.0f / x; a *= tmp; b *= tmp; c *= tmp; ... 1) 这能保证得到相同的答案吗?我想不会,不过确认一下就好了 2) 如果x非常大或非常小,我预计这可能会导致严重的精度损失。有没有一个公式可以告诉我我会牺牲多少准确性 3) 也许没有方便的公式,但我们能至少说明一个经验法则,说明什么时候数值不稳定性会成为一个问题吗?这是
a /= x;
b /= x;
c /= x;
...
因为乘法运算速度更快,所以我们很想这样做
tmp = 1.0f / x;
a *= tmp;
b *= tmp;
c *= tmp;
...
1) 这能保证得到相同的答案吗?我想不会,不过确认一下就好了
2) 如果x
非常大或非常小,我预计这可能会导致严重的精度损失。有没有一个公式可以告诉我我会牺牲多少准确性
3) 也许没有方便的公式,但我们能至少说明一个经验法则,说明什么时候数值不稳定性会成为一个问题吗?这是与操作数的大小有关,还是可能与操作数大小之间的差异有关?我的50美分:
1) 不,第3节进一步解释
2) 我不知道任何公式,所以我跳过这一个
3) 我所知道的经验法则是,尽量只在数量级相近的操作数之间执行运算
实际样本:
您要将数字63.000.000除以1.000.000
使用第一种方法,最终将63*10^6除以1*10^6,它们的震级非常接近
但是,如果您使用第二种方法,那么
temp = 1.0f / x;
将产生10^(-6)
现在,乘以63*10^6*10^(-6)将导致严重的精度损失,因为两者之间的震级差异巨大。CPU将尝试使用10^6数字的指数+分数表示来表示10^(-6)数字
一个可行的替代方案是使用temp
temp = 1 / 1.000;
然后
a = a * temp * temp ;
因为震级将更接近,所以精度损失的可能性更小。当您使用ieee-754数字时,我认为您的方法是完全可以接受的。在ieee-754中,x大约是 mantisa*2指数 其中mantisa是介于1/2和1之间的数字 因此,只要你只进行乘法和除法运算,你当然会有精度损失,但这种损失与
x
(*)的大小无关,并且只与所使用的浮点类型的精度有关(单精度,四精度的双精度,这意味着浮点
,双精度
或长双精度
,具体取决于编译器和体系结构)
(*)只有在不存在底流溢出的情况下,这才是正确的,单精度为1038左右,双精度为10300左右
简历:维基百科上的页面和链接如下: 1)-产生相同的结果?没有保证。对可变性有太多的影响,从486 DX数学协处理器的升级设计(还记得吗?)到编译器实现,再到浮点存储在硬件内存中的方式。() 2)-配方奶粉?我不知道有一个。你说的重大错误是什么意思?在任何情况下,您都可以通过以下方式建立精度预期:
- 理解浮点数(链接2)
- 所使用的变量类型(
,float
,double
)。()long double
- 你在建筑什么样的建筑 32位,还是64位,其他
a/x
或a*(1/x)
,细微的舍入效应也可能导致1或2的不同
2) 如果x
非常小(即比次正态情况下的DBL_MIN
(最小规范化正浮点数)小一点),1/x
是INF
,精度完全损失。如果x
非常大,则可能会出现严重的精度损失,如FP模型不支持次正态分布。通过对最大有限数
=1/DBL|u MAX
进行测试|x |
,代码可以确定何时开始出现严重的精度损失。公式可能取决于所使用的FP模型和x
的指数以及模型的限制。在此范围内,x
和Emin
(或Emax
)的二进制指数之差将是位丢失的一阶估计值
3) 在上面讨论的范围内会出现显著的数值不稳定性。否,这不会导致精度损失。如果操作数都不是非规范的,则有效位总是非常接近。指数很容易调整。只有大小差别很大的加减法通常是有问题的。@Rudy Velthius你说得对。我将修改我的答案并使操作数为denromal。我想用10的幂来强调精度损失,这让我展示了一种情况,事情实际上很容易处理。不同指数的乘法和除法不会造成比平常更多的损失。然而,指数差大的加法和减法会造成很大的损失或精度。考虑有限<代码>双< /代码>数字,让我们假设<代码> x> 0 < /代码>。通常,最大有限值
DBL_MAX
和DBL_MIN
(最小规范化正浮点数)是彼此适当的倒数。由于它们很容易不是彼此的精确数学逆,因此其中一个具有可表示的逆,而另一个则不具有。这就是问题的开始。大多数FP也使用次法线,因此num的范围