带浮点运算的欠流运算

时间:2019-06-24 22:23:52

标签: c# underflow

我正在使用一个包含长数学公式的多个实例的库进行编程,这些实例有时在使用double时会下溢。一个例子可能是:

(Exp(-a*a) - Exp(-b*b))*Exp(c)*Exp(d) 

a,b,c,d也包含一些类似类型的计算。 我可以处理双打出现此错误(并返回适当的错误消息或某些分析界限)的方法,但是如果我没有检测到下溢(例如在指数差异方面),则会导致我无法承受的行为。 (当这种差异缩小为零而其他指数很大时,绝对误差和相对误差都会很大。)

是否存在类似于 checked 关键字的双精度词? 有什么方法可以辅助检查吗?

任何可以确保其正确性的解决方案,即使是提出比必要数量更多的标志的解决方案,对我也有好处。


This question被建议作为重复项,但“对每次乘法之前进行手动检查”对我来说不是一个特别有用的解决方案。

1 个答案:

答案 0 :(得分:3)

  

是否存在类似于checked关键字的双打广告?

不。

  

我可以通过某种方式实施检查吗?

一个不好的解决方案:根据所使用的硬件,浮点运算芯片可能会设置一个标志,指示操作是否下溢。我不建议调用非托管代码来从浮点芯片读取该标志。 (我在原始的Microsoft版本的Javascript中编写了代码来做到这一点,而正确理解这一逻辑是很痛苦的。)

更好的解决方案:您可以考虑编写符号逻辑库。考虑一下例如如果您输入自己的数字类型会发生什么:

struct ExpNumber 
{
  public double Exponent { get; }
  public ExpNumber(double e) => Exponent = e;
  public static ExpNumber operator *(ExpNumber x1, ExpNumber x2) => 
    new ExpNumber(x1.Exponent + x2.Exponent);

以此类推。您可以使用已知的幂定义来定义自己的加,减,幂,对数等。然后,当需要将事情变回两倍时,您可以使用任何稳定的算法来实现,从而避免您喜欢的下溢。

问题在于,有双倍的折衷故意权衡了表示能力和准确性的降低,以大幅提高速度。如果您需要准确表示小于10e-200的数字,则不适合使用双精度。它们旨在解决物理计算中的问题,并且没有那么小的物理量。