[英]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工作的同事。
是否有很大的機會無法可靠地復制這個數字,也許是由於舍入誤差?
浮點舍入誤差的概率static 分析(在編譯時)高於現有技術的 state。 考慮撰寫關於該主題的博士論文。 你的博士導師可能是美國的Patrick Cousot或Eric Goubault或Sylvie Putot或者法國的Emmanuel Haucourt 。 或者來自Frama-C團隊(法國巴黎附近)的一些同事(例如Franck Védrine )。 還可以查看ACM SIGPLAN會議記錄。
也許在 2021 年年中,您可能會使用RefPerSys或Bismon來分析您的 C 代碼(或者您的 Python 代碼;然后另見此)? 在這種情況下,請通過 email 與我聯系。
請注意,浮點舍入錯誤確實殺死了數十人(並且可能解釋了一些波音 737 MAX墜機)。 定點溢出與Ariane 501 故障有關。 因此,您未來的博士學位(關於浮點錯誤的 static 分析)可能由波音、空中客車、美國宇航局、歐空局、達索或CNES共同資助,可能還有國防(炮兵自 1940 年代以來使用計算機)、機器人技術(想想在神經外科)或汽車行業(因為自動駕駛汽車使用浮點)。
另請閱讀已故雅克·皮特拉 (Jacques Pitrat)的博客。 它與您的興趣相關。
2021 年,與浮點相關的一個有趣應用是模擬Covid-19大流行。 所以我想大醫院也可以共同資助你的博士學位(例如,為了更好地估計社會距離……在歐洲,不同國家的推薦距離是不同的)。
當然,在美國, NSF (也許還有谷歌或 Facebook)也可以共同資助你的博士學位(我猜美國國防部也可以共同資助它,因為過去導彈或武器的四舍五入錯誤確實殺死了幾名美國士兵)。
PS。 如果你開始攻讀這些主題的博士學位,請 email 我。 我有興趣。
下面是一個程序,可以幫助您獲得所需的值。 這些值都是在文件<float.h>
中定義的所有常量,並描述了諸如float
或double
精度數使用的常量,以及您可以在程序中使用的最大值和最小值。
DBL_MIN
和DBL_TRUE_MIN
和DBL_EPSILON
值得解釋一下。 您應該閱讀有關浮點二進制數的標准 IEEE 754。 第一個是可以以全精度表示的最小值,在此之下您可以繼續表示數字,但它們會失去越來越多的精度,直到您在DBL_TRUE_MIN
中只生成一個位,這是您機器中可表示的最小值。 但在我看來,您正在尋找的是DBL_EPSILON
,它是浮點中兩個連續數字之間存在的差距。 由於浮點數是相對大小,它以1.0
和1.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
}
它在我的系統上給出的結果是(顯示了float
和double
值):
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.