簡體   English   中英

Java估計一個點的導數

[英]Java estimate a derivative at a point

我目前正在編寫一個計算器應用程序。 我試圖在其中寫一個導數估計器。 下面的公式是一種簡單的方法。 通常,在紙上,您將使用盡可能小的h來獲得最准確的估計。 問題是,雙打無法處理將較小的數字加到相對較大的數字。 例如4 + 1E-200只會得到4.0。 即使h只是1E-16,實際上4 + 1E16也會為您提供正確的值,但是在進行數學運算時這是不准確的,因為第16位之后的所有內容都會丟失,並且舍入不能正確進行。 我聽說雙打的一般經驗法則是1E-8或1E-7。 這個問題是大數字將不起作用,因為2E231 + 1E-8將會是2E23,1E-8將由於尺寸問題而丟失。

f'(x)=(f(x+h)-f(x))/h as x approaches 0

當我在點4這樣f'(4)上測試f(x)= x ^ 2時,它應該恰好是8,現在我知道我可能永遠也不會精確得到8。但是我最准確的似乎是1E- 7或1E8有趣的是1E-9到1E-11都給出相同的答案。 這是h的列表,以及f(x)=x^2 at x=4結果

1E-7 8.000000129015916
1E-8 7.999999951380232
1E-9 8.000000661922968
1E-10 8.000000661922968
1E-11 8.000000661922968
1E-12 8.000711204658728

這是我的問題:

  1. 最佳選擇h的最佳方法是什么,顯然1E-8或1E-7是有意義的,但是我如何基於x來選擇h,因此即使x是3.14E203或2E-231,它也可以使用任何大小的數字。
  2. 我應該計算多少位精度。
  3. 您是否知道德州儀器是如何做到的,TI 83、84和Inspire可以在數值上計算出12位小數或精度的導數,並且幾乎總是正確的,但是無論如何,其數字的最大精度是12位,而那些計算器是非CAS,因此他們實際上並沒有派生任何東西
  4. 從邏輯上講,在1E-7和1E-8之間會有一個數字,它將為我提供更精確的結果,是否可以找到該數字,或者至少可以接近該數字。

回答

非常感謝BobG。 目前,該應用程序計划采用兩種形式,即命令行PC應用程序。 還有一個Android應用程序。 特別感謝您的“關於”頁面部分。 如果您希望它是開源的,但是在我解決一些非常大的錯誤之前,我不會發布指向項目站點的鏈接。 目前我一直稱其為Mathulator,但名稱可能會更改,因為它已經擁有版權並且聽起來很愚蠢。我不知道何時發布候選版本將要運行,目前我不知道何時發布會穩定的。 但是如果我也能實現我想要的一切,它將非常強大。再次感謝。 編程愉快。

有一本書可以回答這個問題(和其他類似的問題):

C ,第二版的數字食譜 ,出版社,Vetterling,Teukolsky和Flannery。 本書還提供C ++,Fortran和BASIC版本。 可悲的是,不存在Java版本。 此外,我認為這本書已經絕版,但可以在線購買某些口味的二手版本(至少通過bn.com)。

第5.7節“數值導數”,第2頁。 186精確地解釋了您在使用數值導數時遇到的問題及其發生原因的數學原理,以及用於正確計算數值導數的函數(在C語言中,但應易於轉換為Java)。 這里給出了它們的簡單近似的總結:

1)從數字上講,最好計算對稱版本:

f'(x)=(f(x + h)-f(x-h))/ 2h

2)h應該大約是(sigma_f)^(1/3)* x_c

哪里

sigma_f =〜 對於簡單函數 ,f(x)計算的分數精度

x_c =〜x,除非x等於零。

但是,這不會導致最優導數,因為誤差為〜(sigma_f)^(2/3)。 更好的解決方案是Ridders算法,該算法在本書中以C程序的形式提供(參見Ridders,CJF 1982,Advances in Engineering Software,第4卷,第2期,第75-76頁)。

閱讀標題為“每個程序員應了解的浮點知識”的論文(為此,請使用Google)。 然后,您將看到大多數浮點值大約在計算機硬件中表示。

要進行計算而沒有此缺點,請使用符號計算。 但這不如使用浮點數有效。

要使浮點結果一致,請使用四舍五入到最接近的10的冪,例如0.1、0.01等。要了解何時應停止逼近,請在近似步驟中使用某種閾值來注意。 例如,如果執行下一個逼近步驟,僅對已計算的值產生0.001%的變化,則沒有理由繼續逼近。

更新我很早以前就有數值計算課程,但是我可以隱約地記得減去接近數非常不好,因為如果數字非常接近,最可靠的數字就會被抵消,而您的數字也不可靠。 當您減小h時,這正是發生的情況。 在這些情況下,建議將減法替換為其他一些操作。 例如,您可以切換到f(x)擴展到的某種系列。

我不太了解您的第二個問題,因為答案取決於您的要求-“您所希望的數量”。

順便說一句,如果您在math.stackexchange.com上找到問題的答案,可能會比較幸運。

此外,訪問thrashgod提供的thrashgod數值微分

1.浮點數(浮點數和雙精度數)的精度取決於數字的絕對值。 雙精度數的精度約為15位,因此您可以加1 + 1e-15 ,但是10 + 1e-15可能又是10,因此您必須做10 + 1e-14 為了獲得有意義的結果,我建議您將1e-8乘以原始數字的絕對值,這將為您提供7個正確的派生數字。 就像是:

double h = x * 1e-8;
double derivative = (f(x+h) - f(x)) / h;

無論如何,這是一個近似值,例如,如果您嘗試計算x = 1e9時sin(x)的導數,則將得到h = 10,結果將全為錯誤。 但是對於“有趣的”部分接近零的“常規”函數,它將很好地工作。

2.“ h”越小,采樣導數的點越精確,但是得到的導數的正確位數越少。 我無法證明這一點,但是我的直覺是,當h = x * 1e-8您將獲得7 = 15 - 8 h = x * 1e-8正確數字,其中15是double的精度。

同樣,使用“更對稱”的公式也是一個好主意,它對二階多項式給出了絕對正確的答案:

double derivative = (f(x+h) - f(x-h)) / (2*h);

我的問題是什么是最合適的h ,如何將其縮放為任意大小。

數值微分中所述, h的合適選擇是sqrt(ɛ) * x ,其中ɛ機器epsilon

我不會將BigDecimal類用於此類計算,盡管它不能回答您的問題,但確實可以提高浮點運算的精度。

根據Javadoc,11位代表指數,而52位代表有效數字。 忽略指數,似乎您有52位要玩。 因此,如果您選擇h = x * 2 ^ -40,則在這里使用了40位,您將看到的精度為2 ^ -12。 根據您的需要調整此比例。

暫無
暫無

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

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