我正在编写一个包含长数学公式的多个实例的库,这些公式在使用 double 时有时会下溢。一个例子可能是:
(Exp(-a*a) - Exp(-b*b))*Exp(c)*Exp(d)
而a,b,c,d也涉及一些类似类型的计算。 我可以处理 double 错误(并返回适当的错误消息或一些分析界限),但如果我没有检测到下溢(例如,在指数的差异上),它会导致我无法承受的行为。 (当这种差异为零而其他指数非常大时,绝对误差和相对误差都可能很大)。
是否有类似于 checked 关键字的东西适用于 double ? 有什么方法可以辅助实现检查吗?
任何确保其正确的解决方案,即使是提出比必要更多的标志的解决方案对我来说都是好的。
This question被建议为重复但“在每次乘法之前手动检查”对我来说不是一个特别有用的解决方案。
最佳答案
Is there something similar to checked keyword that works for doubles?
没有。
Is there some way I can implement checks in an assisted way?
一个糟糕的解决方案:根据您使用的硬件,浮点运算芯片可能会设置一个标志,指示操作是否下溢。我不建议调用非托管代码来读取浮点芯片上的标志。 (我在原始的 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);
等等。您可以使用已知的幂恒等式定义自己的加法、减法、幂、对数等。然后,当需要将事情变回 double 值时,您可以使用任何稳定的算法来实现它,避免您喜欢的下溢。
问题在于, double 有意以降低表现力和准确性来换取速度的大幅提高。如果您需要准确表示小于 10e-200 的数字, double 不适合您;它们旨在解决物理计算中的问题,并且没有这么小的物理量。
关于c# - 带浮点算术检查的下流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56744649/