我可以可靠生成的最小非零数是多少?

问题描述

我正在做一些图形类型的东西,我经常想将两点之间的斜率作为 dy / dx。但是,如果我的 dx 恰好为零,则会得到除以零错误

如果 dx 为零,我可以将其设置为较小的值,例如 0.001。但是,我想提高我的解决方案的准确性。

对于这个给定的问题可能有更好的解决方案,但我确信存在其他问题,其可能的解决方案要求同样的事情:最小可能的非零数。

另外,获得它有多贵?这个数字是否有很大可能无法可靠地复制,可能是由于舍入错误

解决方法

您可以为此使用 decimal 模块吗?你可以用这个制作一个非常小的固定浮点值:

import decimal
from decimal import Decimal

>>> almost_zero = Decimal((0,(1,),decimal.getcontext().Emin))
>>> almost_zero
Decimal('1E-999999')

这是一个非常小的数字,应该适合您的目的。

>>> 1 / almost_zero
Decimal('1E+999999')

或者你可以从sys.float_info中挖掘一些东西。

>>> import sys
>>> sys.float_info
sys.float_info(max=1.7976931348623157e+308,max_exp=1024,max_10_exp=308,min=2.2250738585072014e-308,min_exp=-1021,min_10_exp=-307,dig=15,mant_dig=53,epsilon=2.220446049250313e-16,radix=2,rounds=1)
>>> almost_zero = sys.float_info.min
>>> 1 / almost_zero
4.49423283715579e+307
,

我正在做一些图形类型的东西

然后考虑研究(寻找灵感)GNUplot 的源代码。它是 free software.... 也看看 GraphViz 的源代码。是 open source

我可以可靠生成的最小非零数是多少?

理论上,这可能是特定于编译器的,也可能是特定于实现的。

n1570 草案 C 标准在 §5.2.4.2.2 中提到了一些 DBL_EPSILON 宏....

我建议明确地 if (dy==0.0) return; 编码,因为在当前的计算机上它非常快。实际上,像 if (fabs(dy)<4.0*DBL_EPSILON) return; 这样的测试可能会更好(但会运行得更慢)。

关于您的 C 代码中的 rounding errors(在实践中),请参阅 floating point guide 并考虑使用 Fluctuat toolCADNA tool 或 {{3} }.

如果您想分析二进制可执行文件中的舍入错误,请联系我从事 ABSINT tool 工作的同事。

您也可以使用一些 BinSec 库,例如 arbitrary-precision arithmetic

这个数字是否有很大可能无法可靠地复制,可能是由于舍入错误?

浮点舍入误差的概率 GMPlib(在编译时)高于现有技术水平。考虑就该主题撰写博士论文。您的博士生导师可能是美国的 static analysis 或法国的 Patrick CousotEric Goubault,也可能是 Sylvie Putot。或者来自 Emmanuel Haucourt 团队(法国巴黎附近)的一些同事(例如 Franck Védrine)。还可以查看 Frama-C 会议记录。

也许在 2021 年年中,您可能会使用 ACM SIGPLANRefPerSys 来分析您的 C 代码(或者您的 Python 代码;然后另见 Bismon)?在这种情况下,请通过电子邮件与我联系。

请注意,浮点舍入错误确实导致数十人死亡(并且可能解释了一些 this 崩溃)。定点溢出与 Boeing 737 MAX 相关。因此,您未来的博士学位(浮点错误的静态分析)可以由 Ariane 501 failureBoeingAirbusNASAESADassault 和可能的国防(炮兵自 1940 年代以来就使用计算机)、机器人技术(想想神经外科中的 CNES)或汽车行业(因为 cobots 使用浮点数)。

另请阅读已故 Jacques Pitrat 的 autonomous vehicles。它与您的兴趣相关。

2021 年,一个与浮点相关的有趣应用是模拟 the blog 大流行。所以我想大医院也可以共同资助你的博士(例如,为了更好地估计Covid-19......在欧洲,不同国家/地区的推荐距离不同)。

当然,在美国,social distancing(或许还有 Google 或 Facebook)也可以共同资助你的博士学位 (我猜美国 NSF 也可以共同资助它,因为过去导弹或武器的四舍五入错误确实杀死了几名美国士兵)。

附注。如果您开始攻读这些主题的博士学位,请给我发电子邮件。我有兴趣。

,

下面的程序可以帮助您获得所需的值。这些值都是在文件 <float.h> 中定义的常量,并描​​述了诸如 floatdouble 使用的位数以及您可以在程序中使用的最大值和最小值等常数。

DBL_MINDBL_TRUE_MINDBL_EPSILON 值得一些解释。您应该阅读有关浮点二进制数的标准 IEEE 754。第一个是可以以全精度表示的最小值,在此之下您可以继续表示数字,但它们会失去越来越多的精度,直到您在 DBL_TRUE_MIN 中仅生成一个位,这是可表示的最小值你的机器。但在我看来,您正在寻找的是 DBL_EPSILON ,它是浮点中两个连续数字之间存在的差距。由于浮点数是相对大小,它是由 1.01.0 之后的下一个数字之差给出的,这意味着数字不能比这更接近(您需要乘以这个 *_EPSILON }} 通过提供比例的数字来获取该比例下一个数字与下一个数字的距离。

为您提供值的程序如下:

#include <stdio.h>
#include <float.h>

#define P(_nam,_fmt) printf("%20s = "_fmt"\n",#_nam,_nam)

int main()
{
        P(FLT_DIG,"%18d");
        P(FLT_MAX,"%18.6g");
        P(FLT_EPSILON,"%18.6g");
        P(FLT_MIN,"%18.6g");
#if FLT_HAS_SUBNORM
        P(FLT_TRUE_MIN,"%18.2g");
#endif
        puts("");
        P(DBL_DIG,"%18d");
        P(DBL_MAX,"%18.15lg");
        P(DBL_EPSILON,"%18.15lg");
        P(DBL_MIN,"%18.15lg");
#if DBL_HAS_SUBNORM
        P(DBL_TRUE_MIN,"%18.2lg");
#endif
}

它在我的系统上给出的结果是(显示了 floatdouble 值):

             FLT_DIG =                  6
             FLT_MAX =        3.40282e+38
         FLT_EPSILON =        1.19209e-07
             FLT_MIN =        1.17549e-38
        FLT_TRUE_MIN =            1.4e-45

             DBL_DIG =                 15
             DBL_MAX = 1.79769313486232e+308
         DBL_EPSILON = 2.22044604925031e-16
             DBL_MIN = 2.2250738585072e-308
        DBL_TRUE_MIN =           4.9e-324