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 Function
testiohjelma, 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