C# og to matematiske funktioner: Math2 klassen

Tags:    .net c#
Skrevet af Bruger #4522 @ 24.09.2007

Introduktion


En gang i tidernes morgen havde jeg i et Java-projekt brug for nogle matematiske funktioner udover hvad der fandtes i Javas Math klasse; helt specifikt drejede det sig om de hyperbolske trigonometriske funktioner, Gammafunktionen og logaritemfunktionen med grundtallet 2. Det var ophavet til min Math2 klasse i Java.

Nu arbejder jeg så i .NET/C# og skulle for nylig igen bruge de omtalte matematiske funktioner, så derfor hev jeg den på daværende tidspunkt gamle Math2 klasse frem og konverterede koden til .NET (hvilket er meget nemt). .NETs System.Math klasse havde allerede de hyperbolske trigonometriske funktioner (de er sidenhen også kommet i Javas Math klasse) så min .NET Math2 klasse indeholder kun to statiske funktioner: nemlig Gamma-funktionen og logaritmefunktionen med grundtallet 2.

Denne artikel beskriver kort denne klasse. Det er ikke lang artikel, men i OOPs ånd (genbrug, genbrug og atter genbrug) skriver jeg denne artikel da andre måske kunne få nytte af det. Artiklen vil kort berøre nogle matematiske emner, men da datalogi til dels bygger på matematik burde de fleste programmører ikke have problemer med at stifte bekendtskab med lidt matematik.

Artiklen vil kort beskrive de to pågældende matematiske funktioner for at give lidt baggrund og selvfølgelig vise hvordan de er implementeret. Til sidst er gengivet hele kildekoden til .NET Math2 klassen. Det skal bemærkes, at da jeg først lavede min Math2 C# klasse, overså jeg den overlæssede Log funktion som kan bruges til at udregne logaritmen i hvilket som helst gurndtal, den kunne jeg have anvendt i stedet for min egen Log2 funktion. For komplethedens skyld har jeg dog ladet min Log2 funktion være i Math2 klassen.

Logaritmefunktionen


De fleste af os kender logaritmefunktionen fra skolen, gymnasiet og/eller videregående uddannelse. Mange kender dog kun til logaritmefunktionen som en tast på lommeregneren, hvilet er lidt ironisk set i dets historie.

Logaritmefunktionen blev opdaget/opfundet i 1600-tallet og blev meget populær som en hurtig måde at udregne produkter på. Den tids udregninger blev jo foretaget manuelt og beregningen af store produkter var tit besværlig, men brugen af logaritme gjorde det meget nemmere. Logaritmefunktioen er den inverse funktion til eksponentialfunktionen - dvs. de udligner hindanden.

En logaritmefunktion har et grundtal. De to mest almindelige logaritmefunktioner er 10-tals logaritmen og den naturlige logaritme; de har henholdsvis grundtallet 10 og e (e er en matematisk konstant: e = 2.71828 18284 59045 23536...).

.NETs System.Math klasse har følgende funktioner til udregning af logaritmer:

Fold kodeboks ind/udKode 


Siden jeg har brug for logaritmefunktionen med grundtallet 2 (Log2), skal jeg finde en måde hvorpå jeg kan udregne Log2 ud fra de allerede eksisterende funktioner. Og det er heldigvis nemt:


log_b(a) = log_z(a) / log_z(b)


Med andre ord er logaritmen af a med grundtallet b det samme som logaritmen af a med grundtallet z divideret med logaritmen af b med grundtallet z. Og jeg kan frit vælge z.

Ved at vælge z som værende den matematiske konstant e får vi for vores ønskede 2-tals logaritme:


log_2(a) = ln(a) / ln(2)


ln er den naturlige logaritme som i C# er Log funktionen. Vores C# kode for Log2 bliver derfor:

Fold kodeboks ind/udKode 


Gammafunktionen


Vores anden ønskede funktion er Gammafunktionen. Gammafunktionen er i familie med fakultet. Hvor den ordinære fakultet kun er gældende for ikke negative heltal, kan Gammafunktionen bruges til at udregne fakultet af både reelle og komplekse tal. Den bruges også til at løse visse typer anden-ordens differentialligninger.

Gammafunktionen er givet ved følgende integral:



Vi kan selvfølgelig ikke implementere et integral i et computerprogram, så vi skal finde en approksimation.

For at gøre an lang historie omkring numerisk analyse kort, så var det en fyr der hed Lanczos der udledte den mest kendte approksimation (over årene er der blevet udledt flere forskellige approksimation på Gammafunktionen).

Approksimationen ser ud som følger:



Formlen ser måske lidt skræmmende ud hvis man ikke er vant til matematik, men hvis man tager hver enkelt del for sig foregår der slet ikke noget kompliceret her. Det græske symbol gamma og N er to konstanter, og vi får den mindste fejl på approksimationen hvis de antager værdierne 5 og 6.

C er en tabel af koefficienter, som jeg putter i en array i Math2 klassen. Da N = 6 og jeg også har en c[0] har jeg kun udregnet de første 7 koefficienter. Hvis man er interesseret i hvordan de udregnes se ovenstående Lanczos wikipedia side.

Vi kan nu umiddelbart konvertere ovenstående til følgende C# kode:

Fold kodeboks ind/udKode 


Den endelige kode


Vores endelige kode består af to filer. Den første, Math2.cs, er vores nye Math2 klasse med Log2 og Gamma:

Fold kodeboks ind/udKode 


Den anden fil, Program.cs, er en såkaldt driver der tester vores nye Math2 klasse:

Fold kodeboks ind/udKode 


Hvis man kører testen ser man at vores Gammafunktion er en udmærket approksimation.

Så hvis du står og skal bruge Gamma (eller Log2) så er de her til fri benyttelse.

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (5)

User
Bruger #6559 @ 24.09.07 20:43
Jeg har læst artiklen og..... ja... det ligger på et noget højere niveau end jeg pt befinder mig på, selv i matematik, så jeg venter med at rate til jeg lige har forstået matematikken bag. Men ellers ser det godt ud. Desværre kan jeg ikke se hvor man lige bruger det:)
User
Bruger #285 @ 26.09.07 22:08
Fin artikel.

I Gammafunktionen ville det nok være smart at erklære c og N som en const således den bliver kompileret til konstanter, og dermed ikke behøver overleve til run-time. Tilsvarende burde der nok være et check af om z > 0 for ikke at lave noget nuldivisionsgris :-)
User
Bruger #4522 @ 27.09.07 11:24
Hej mikl-dk,

Tak for dine fine kommentarer, som er fuldstændig rigtige. :)
User
Bruger #285 @ 29.09.07 15:39
Hej Jacob Rohde,

Selv tak. Dejligt med nogle lidt mere teoretiske artikler :-)
User
Bruger #5620 @ 30.10.07 23:15
Ifølge MSDN så er der altså også en tredje log function i .Net

Log(double,double)

hvor den anden double er basen
Du skal være logget ind for at skrive en kommentar.
t