Kirjoittaja: tnb
Kirjoitettu: 26.02.2004 – 26.02.2004
Tagit: matematiikka, koodi näytille, vinkki
Ketjumurtoluku (continued fraction) on menetelmä, jolla voidaan laskea hyvin tarkkoja desimaaliarvoja funktioille kuten sin(), gamma(), beta(), PI joiden arvot ovat periaatteessa päättymättömiä desimaalilukuja. Ohessa esimerkki sin() function laskennasta. VB:ssä funktio voi kutsua itseään, jolloin ketjumurtoluvun laskenta on helppoa. Menetelmää kutsutan myös rekursioksi.
Function sine(ByVal x As Double) As Double
'sin(x) functio, tarkkuus noin 10^-15
If x < 0 Then sine = -sine(-x) : Exit Function
Dim x3 As Double = Math.PI * Math.Floor(x / Math.PI) ' monesko jakso
Dim x2 As Double = x - x3 'palautettu nollan lähelle
sine = x2 / (1 + x2 ^ 2 / ketjumurtoluku(x2, 0))
If Int(x3) Mod 2 = 1 Then sine = -sine 'joka toinen on negatiivinen
End Function
Function ketjumurtoluku(ByVal x As Double, ByVal k As Integer)
'tarvitaan sin() laskussa
k = k + 2 'syvyyslaskuria kasvatetaan
If k = 30 Then ketjumurtoluku = 1 : Exit Function 'riitävän syvä, palataan ylemmäs
Dim k2 As Double = k * (k + 1)
Dim x2 As Double = x * x
ketjumurtoluku = (k2 - x2) + (k2 * x2) / ketjumurtoluku(x, k) 'kutsutaan itseä
End Functiontestiohjelma, buttoniin
Dim i As Integer
Dim x As Double
Dim t1, t2 As Date
Dim ts As TimeSpan
t1 = Now()
For i = 1 To 10000
sine(1)
Next
t2 = Now()
ts = t2.Subtract(t1)'käytetty aika
TextBox1.Text = (sine(1))
TextBox3.Text = (Math.Sin(1)) 'vb:n sisäinen funktio
TextBox2.Text = (ts.TotalMilliseconds)tästähän oli jopa hyötyä :)
Mietin joskus itsekin, miten tällaisen saisi aikaan. Ajattelin, että jos alusta voisi jotenkin poistaa desimaaleja niin, että ne voitaisiin korvata seuraavilla desimaaleilla, ja sitten tallentaa molemmat desimaaliluvut omiin DOUBLE-muuttujiin ja tarpeen tullen yhdistää. En tiedä kyllä, onko tässä lähellekään sama periaate, kun en oikein äkkiseltään koodista näe, mitä tuo tekee.
huh, hieano mutten tajua mitään, kiva kun joku osaa :P
Kiinnostava aihe mutta taitaa olla VB.NETillä.
Testiohjelmassa luvataan tarkkuudeksi 10^-15 mutta sillä tarkkuudellahan sinin saa suoraan ilman rekursioita.
Minulla on ollut ehkä samankaltaisia ajatuksia kuin hunajavohvelilla eli olen pilkkonut pitkät luvut osiin ja saanut näin numeroita niin pitkän rimpsun kuin katsoa sietää eli töllöön mahtuu. Jollei yhteen ruutuun niin sitten vierittämällä. Seinällä on pii 10000 desimaalin tarkkuudella ja ajatuksena oli tarkistaa, onko desimaalit oikein.
Tässä myös PI:n laskenta:
Function PII() As Double
PII = 3 + 1 / ketjumurtoluku2(0)
End Function
Function ketjumurtoluku2(ByVal k As Double) As Double
' PII laskentaan
k = k + 1
Dim jakajat() = {3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3}
If k > 13 Then ketjumurtoluku2 = 0 : Exit Function
ketjumurtoluku2 = jakajat(k) + 1 / ketjumurtoluku2(k)
End Function