簡體   English   中英

Haskell中使用系列的自然對數給出不精確的結果

[英]Natural Logarithm using series in Haskell Gives Imprecise Results

所以我寫了兩個函數來計算變量x的自然對數,將增量和的上限增加到33000之后,與從Prelude導入的默認對數函數相比,這些函數仍返回在ghci中測試的不精確結果,這是代碼定義:

lnOfx :: Float -> Float
lnOfx x = netSum f 1 33000
    where f i = 2*(1/oddTerm)*((x-1)/(x+1))**oddTerm
            where oddTerm = 2*i-1
          netSum f minB maxB = sum [f i | i <- [minB .. maxB]]

lnOfx2 :: Float -> Float
lnOfx2 x = netSum f 1 33000
       where f i = (1/i)*((x-1)/x)**i
             netSum f minB maxB = sum [f i | i <- [minB .. maxB]]

和測試結果:

log 3
1.0986122886681098
lnOfx 3
1.0986125
lnOfx2 3
1.0986122

log 2
0.6931471805599453
lnOfx 2
0.6931472
lnOfx2 2
0.6931473

那么,為什么結果不同?正確計算自然對數的正確方法(如Prelude的對數函數)是什么?

浮點數學運算很棘手。 可能導致精度損失的一件事是相加幅度相差很大的數字。 例如,在以i=25開頭的算法中,總和中的項很小,以至於它們不再起作用:

-- 25t term:    
let f x i = let oddTerm = 2*i-1 in 2*(1/oddTerm)*((x-1)/(x+1))**oddTerm
let y = f 3.0 25

-- summation up to 24 item
let s = 1.098612288668109

-- this will return True, surprisingly!
s + y == s

為減輕這種情況,您可以做的一件事是按相反的順序添加數字,因此,在將較小的數字添加到較大的數字之前,先將它們相加。

lnOfx :: Float -> Float
lnOfx x = netSum f 1 33000
    where f i = 2*(1/oddTerm)*((x-1)/(x+1))**oddTerm
            where oddTerm = 2*i-1
          netSum f minB maxB = sum $ reverse [f i | i <- [minB .. maxB]]

在我的測試中,這足以使print (lnOfx 3.0)print (log 3.0)顯示所有相同的數字。

但總的來說,我建議閱讀一本數值分析書,以了解有關此類問題的更多信息。

暫無
暫無

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

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