máj
26

Modulok az F#-ban

Címkék: referencia module f# | Szerző: sync | 5:37 pm

 

Egy korábbi blogomban egy THM számítási függvényt valósítottam meg F#-ban. Korábban csak interaktivan futtattam. Hogyan használhatnám ezt a függvényt C#-os projektben. Az F# nem igazán alkalmas UI programozására, de mint .NET nyelv, referenciát addhatunk saját fejlesztésű projekteinkre egy C# vagy bármilyen más .NET nyelvben írt alkalmazásban.

1. Ehhez hozzunk létre egy F# Library projektet.

2. Definiáljuk a namespace-t.

3. Hozzunk létre egy vagy több osztályt: míg a module statikus osztályok, addig a type dinamikus osztályok létrehozására való. Használhatjuk a láthatósági módosítókat.

 namespace FSharp.Bank

module THM =
    let private je Ak  i  m  = truncate(Ak/(1.0 + i/100.0)**(m/12.0))
           
    let rec THMSzamitas Ak  i m  =  
            match m with
            | 0.0 -> 0.0
            | _ -> (je Ak  i  m ) + (THMSzamitas Ak i (m - 1.0) )

4. Buildeljük a projektet.

5. A dll-t hozzáadhatjuk referenciaként egy másik .NET-es projekthez.

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FSharp.Bank;


namespace THMSzamitas
{
    class Program
    {
        static void Main(string[] args)
        {
            for (double i = 1; i < 30; i++)
            {
                Console.WriteLine(String.Format("{0}. {1:c}", i, THM.THMSzamitas(73565d, i, 240)));
            }
            Console.ReadKey();
        }
    }
}

máj
25

Kicsit elhanyagoltam mostanában az F#-ot. Tanfolyamokra járok, munka után kell loholnom.  De a bejelentés ismét az F# felé fordította a figyelmemet. Megjelent az új F# CTP. Don Syme blogja részletesen taglalja az újdonságokat.  Az eddigi, szerény kódjaim futnak, csak a nyelvi parser nem.  Ami számomra érdekes, hogy a "#light" default lett, azaz nem kell explicit megadni. "#light off" -fal ki lehet kapcsolni. Néhány függvény neve is megváltozott, pontosabban camel case -esitve lett. Pl. tryfind helyett tryFind. Az F# -ot integrálták a VS 2010 bétába, ahol is fejlettebb debugra lesz lehetőség. Sajnos kódjaim egyszerűsége miatt a többi változásnak nem kell örülni.

 

máj
4

THM-számítás

Címkék: thm f# teljes hiteldíj mutató | Szerző: sync | 8:56 pm

Kicsit utánajártam, hogy mit is jelent a banki THM, azaz a Teljes Hiteldíj Mutató. Sokunknak az a naív elképzelése, hogy a THM nem más, mint a felvett hitel és visszafizetett összeg százalékos aránya. Ez  csak olyan esetekben igaz, ahol alacsony a kamatláb, illetve rövid a futamidő.

A jogszabály szerint a banki hírdetésekben megadott THM-t 5 millió forint után és 20 év futamidővel kell kiszámolni a következő képlettel:

 

 

 

 

 

 

Megnéztem az MKB honlapján, hogy mennyi THM-t számol a kalkulátor:

A havi törlesztő részlet összege:

73.565 Ft

THM:

19,02 %

Nézzük, hogy helyes-e a 19,02% THM

A fenti képlet F# -ban:

#light

open Microsoft.FSharp.Math

let je Ak  i  m  = truncate(Ak/(1.0 + i/100.0)**(m/12.0));;
           
let rec thm_szamitas Ak  i m  =  
            match m with
            | 0.0 -> 0.0
            | _ -> (je Ak  i  m ) + (thm_szamitas Ak i (m - 1.0) )

 Keressük meg, hogy milyen belső megtérülési rátánál kapunk 5 milliót. Ehhez 1 és 30 közötti THM-mel futtatom a képletet. A jó THM-nél lesz a kiszámított érték éppen 5.000.000 Ft.

seq[for i=1 to 30  do yield printfn "%A ; %f" i (thm_szamitas 73565.0 (float i) 240.0)]

 A futási eredmény:

1 ; 16003018.000000 2 ; 14566444.000000 3 ; 13313045.000000 4 ; 12215542.000000

5 ; 11251169.000000 6 ; 10400825.000000 7 ; 9648455.000000 8 ; 8980526.000000

9 ; 8385613.000000 10 ; 7854026.000000 11 ; 7377482.000000 12 ; 6948995.000000

13 ; 6562530.000000 14 ; 6212946.000000 15 ; 5895790.000000 16 ; 5607276.000000

17 ; 5344084.000000 18 ; 5103362.000000 19 ; 4882637.000000 20 ; 4679738.000000

21 ; 4492777.000000 22 ; 4320093.000000 23 ; 4160242.000000 24 ; 4011975.000000

25 ; 3874136.000000 26 ; 3745736.000000 27 ; 3625907.000000 28 ; 3513860.000000

29 ; 3408911.000000 30 ; 3310439.000000

 

Láthatjuk, hogy a megtérülési ráta 18% és 19% között éri el az 5 millió forintot.

Az MKB 19,02%-ot ad meg. Az MKB és az én számításom között van némi különbség, ami  a kerekítésekből, vagy más - általam nem ismert- okokból(pl. költségek, nem havi kamatperiódus, kamatkockázat)  adódhat. 

 

Excelben grafikonnal ábrázolva:

ápr
25

F# kezdetek III.

Címkék: option match yield f# seq | Szerző: sync | 1:13 pm

Gyakran találkozni F# kódókban a Some(valamilyen kifejezés) -sel. A Some az opciós értékekkel van kapcsolatban. Az option definíciója a Discriminativ Unions tárgykörébe tartozik.:

type 'a option =
| None
| Some of 'a

 azaz a definíció szerint bármely kifejezés option-je None vagy Some. Kicsit nehéz megérteni, hogy miképpen működik.  Tehát, egy kifejezésnek az option-je vagy None vagy maga a kifejezés. Ez jól jön olyankor, amikor vizsgálni akarjuk, hogy egy függvény ad-e vissza valamit vagy null-lal tér vissza.

pl.

Some(89)

>val it : int option = Some 89

Some(None)

>val it : 'a option option = Some null 

 

A következő példában háromféle szekenciát hozok létre. Látható, hogy egy lista létrehozása is milyen rugalmas. Az első egy számlista 1-99 között, a második egy egész szám- négyzete párosokat, míg a harmadik egy string listát hoz létre a windows mappa fájljaiból. Mindhárom listát ugyanazzal a benne_van függvénnyel vizsgálhatjuk. A C#-ban sokat kellene gondolkodni egy ilyen tömör megoldáson.

Van még egy érdekes elem a lista3 definiciójában: a yield. Ha egy függvény eredménye egy nagyon nagy lista(a példában a c:\Windows fájllistája), a yield-del megakadályozzuk, hogy létrejöjjön  minden elemével. A  függvény végrehajtása felfüggesztődik(az állapotát megőrizve), és csak akkor folytatódik, amikor további elemekre is szükségünk van. Itt egy blog erről magyarul, C#-ban.

#light
open System
open System.IO

let lista = seq[1..99];
let lista2 = seq[for i=1 to 100 do yield (i,i*i)];
let lista3 = seq[for file in Directory.GetFiles("c:\\windows") do
                     yield (Path.GetFileName(file))];

 

A benne_van függvényben a match-csel vizsgálom, hogy a tryfind eredménye "valami" vagy "semmi". 

 let benne_van lista func = match lista|>Seq.tryfind(func) with
                            |Some(j) -> printfn "Igen, %A" j
                            |None -> printfn "Nincs";;


  benne_van   lista (fun x-> x=20)
benne_van   lista2 (fun x-> snd(x)=100)
benne_van   lista3 (fun x-> x.Contains(".exe"));;

  

 

 

 

 

ápr
23

Nyelvi parser

Címkék: f# nyelvi parser | Szerző: sync | 7:19 pm

Chris Smith blogja ihletett meg egy nyelvi parser megírására. Már régen izgatott, hogy miképp lehetne normális emberi nyelven megírni egy kérdést, amire a program értelmes választ is ad. Nem egyszerű dolog, de az F# csodákra képes. Néhány óra alatt persze, nem lehet tökéletest alkotni, de azért elégedett vagyok az eredménnyel. A lényeg, hogy azokat a szavakat felveszem tokenként, amelyek ennek a kis folyó-adatbázisnak a lekérdezésére lehet használni : ("Melyik", "folyó", "hosszabb/rovidebb", "mint", "a" 'valamelyik folyó').

Ezekből a tokenekből az fslex segédprogram egy parsert generál. Ami talán érdekes - nem találtam rá példát - hogyan lehet egy tetszőleges folyónevet megadni. A mellékelt forrásban* megtalálható a válasz.

A folyó adatbázisom :

 

let rivers = [("Nilus", 6690);("Mississipi", 6200);("Jangce", 5800);("Duna",2842);("Amur", 5780);("Don", 1870);("Amazonas", 6500);]

 

 

Ilyen jellegű a kérdésekre tudok válaszolni:

  "Melyik folyo hosszabb mint az Amazonas "
 "Melyik folyo rovidebb mint a Duna "

 

>Nilus(6690) hosszab mint a(z) Amazonas(6500)

>Don(1870) rvidebb mint a(z) Duna(2842)

A kérdések tovább bővíthetők. A mintaillesztős az F# erőssége. A match használata teszi lehetővé, hogy ennyire tömör legyen a kód.

*A mellékelt F# projekt nálam néha működött, néha nem. Az F# interpreter néha megbolondul. Garanciát nem tudok adni.

 

ápr
15

F# kezdetek II.

| Szerző: sync | 9:06 am

F# programocskák VS 2008 interaktív módban gyorsan kipróbálhatók. Ehhez a szkript fájl(.fsx) első sorába a #light szót kell írni, ami azt jelenti, hogy használhatjuk a könnyített szintaxist. A blokkokat nem kell jelölni begin-nel és end -del, hanem elég behúzással jelölni azokat. Ekkor viszont a szkripter szól, ha rosszak a tabulációk. Az egyes függvényeket két darab pontosvesszővel le kell zárni.

ápr
14

F# kezdetek

Címkék: lépések kezdeti f# | Szerző: sync | 8:20 am

 

Most, hogy a fiammal készülgetünk a matek érettségijére, a faktoriális számítására készítettem  C#-ban egy kis programot. Nincs is ezzel különösebb gond. Rekurzív függvényhívás, csak ügyelni kell arra, hogy legyen kilépési pont:
 
public static long Factorial(long number)
 {
            if (number ==0)
                return 1;
            else
                return number * Factorial(number - 1);
    }

 

A baj az ezzel, hogy csak 20!–ig használható. Kis guglizás során valahol ráakadtam az F#-ra. Ezen a nyelven n! számítására:
süti beállítások módosítása