带浮点算术检查的下流

Under flow with floating point arithmetic checking

我正在编写一个包含长数学公式的多个实例的库,这些公式在使用双精度数时有时会下溢。一个例子可以是:

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

而a,b,c,d也涉及一些类似类型的计算。 我可以处理双打错误(和 return 适当的错误消息或一些分析界限)但是如果我没有检测到下溢(例如指数的差异)它会导致我无法承受的行为. (当此差异为零而其他指数非常大时,绝对误差和相对误差都可能很大)。

是否有类似于 checked 关键字的东西适用于双打? 有什么方法可以辅助执行检查吗?

任何确保其正确的解决方案,即使是提出比必要更多的标志的解决方案对我来说都是好的。


被建议作为副本,但 'manually check before every multiplication' 对我来说不是一个特别有用的解决方案。

Is there something similar to checked keyword that works for doubles?

没有。

Is there some way I can implement checks in an assisted way?

一个糟糕的解决方案:根据您使用的硬件,浮点运算芯片可能会设置一个标志,指示操作是否下溢。我不建议调用非托管代码来读取浮点芯片上的标志。 (我在 Javascript 的原始 Microsoft 版本中编写了代码来执行此操作,但很难正确理解该逻辑。)

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

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 的数字,双打不适合您;它们旨在解决 物理计算 中的问题,并且没有这么小的物理量。