簡體   English   中英

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

[英]What is the Smallest Nonzero Number that I can Reliably Generate?

我正在做一些圖形類型的東西,我經常想將兩點之間的斜率作為 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的源代碼。 它是免費軟件....還可以查看GraphViz的源代碼。 它是開源的。

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

理論上,這可能是特定於編譯器的,也可能是特定於實現的。

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

if (dy==0.0) return;我建議明確編碼; 因為在當前的計算機上速度非常快。 實際上,像if (fabs(dy)<4.0*DBL_EPSILON) return; 可能會更好(但運行速度會更慢)。

關於 C 代碼中的舍入誤差(在實踐中),請參閱浮點指南並考慮使用Fluctuat 工具CADNA 工具ABSINT 工具

如果您想分析二進制可執行文件中的舍入錯誤,請聯系我從事BinSec工作的同事。

您還可以使用一些任意精度的算術庫,例如GMPlib

是否有很大的機會無法可靠地復制這個數字,也許是由於舍入誤差?

浮點舍入誤差的概率static 分析(在編譯時)高於現有技術的 state。 考慮撰寫關於該主題的博士論文。 你的博士導師可能是美國的Patrick CousotEric GoubaultSylvie Putot或者法國的Emmanuel Haucourt 或者來自Frama-C團隊(法國巴黎附近)的一些同事(例如Franck Védrine )。 還可以查看ACM SIGPLAN會議記錄。

也許在 2021 年年中,您可能會使用RefPerSysBismon來分析您的 C 代碼(或者您的 Python 代碼;然后另見此)? 在這種情況下,請通過 email 與我聯系。

請注意,浮點舍入錯誤確實殺死了數十人(並且可能解釋了一些波音 737 MAX墜機)。 定點溢出與Ariane 501 故障有關。 因此,您未來的博士學位(關於浮點錯誤的 static 分析)可能由波音空中客車美國宇航局歐空局達索CNES共同資助,可能還有國防(炮兵自 1940 年代以來使用計算機)、機器人技術(想想在神經外科)或汽車行業(因為自動駕駛汽車使用浮點)。

另請閱讀已故雅克·皮特拉 (Jacques Pitrat)的博客 它與您的興趣相關。

2021 年,與浮點相關的一個有趣應用是模擬Covid-19大流行。 所以我想大醫院也可以共同資助你的博士學位(例如,為了更好地估計社會距離……在歐洲,不同國家的推薦距離是不同的)。

當然,在美國, NSF (也許還有谷歌或 Facebook)也可以共同資助你的博士學位(我猜美國國防部也可以共同資助它,因為過去導彈或武器的四舍五入錯誤確實殺死了幾名美國士兵)。

PS。 如果你開始攻讀這些主題的博士學位,請 email 我。 我有興趣。

下面是一個程序,可以幫助您獲得所需的值。 這些值都是在文件<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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM