Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Perl: Tk-kirjasto: Binomitodennäköisyys

koodaaja [04.07.2021 11:09:47]

#

Tämä ohjelma käyttää Perlin Tk-kirjastoa ja laskee binomitodennäköisyyden. Binomitodennäköisyys koostuu binomikertoimesta (toistot ja onnistumiset) ja todennäköisyydestä. Binomitodennäköisyydessä jokaisen onnistumisen todennäköisyys on yhtä suuri eikä riipu edellisistä onnistumisista. Binomikerrointa varten pitää laskea kertoimet toistolle, onnistumiselle ja niiden erotukselle.

Toistokoe on koe, jossa testataan binomitodennäköisyyttä. Toistokokeessa toistetaan tietty määrä tiettyä asiaa peräkkäin ja todennäköisyys tietylle onnistumiselle on aina sama. Esimerkiksi nopan heitto on toistokoe, mutta korttipakka, johon ei korttia palauteta ei ole toistokoe.

Tämä ohjelma laskee onnistumisen tietylle määrälle onnistumiselle sekä kuinka todennäköistä on että enintään tietty määrä onnistuu.

use Tk;

#Tämä ohjelma laskee binomitodennäköisyyden, joka koostuu toistoista, onnistumisista ja todennäköisyydestä.
#Toistot ja onnistumiset muodostavat binomikertoimen
$main = MainWindow->new;
$main->title("Binomitodennäköisyys");

my $teksti = "";

#Luodaan kontrollit.
#Tiedot tallennetaan listaan.

my $nappain = $main->Button(-text=>"Laske", -command=>\&laske)->pack();
my $lappu = $main->Label(-textvariable=>\$teksti)->pack();
my $tlaatikko = $main->Entry()->pack();
my $lista = $main->Listbox(-selectmode=>"single")->pack();

$teksti = "Toistot, onnistumiset, tn";


sub Kertoma($){
 #Lasketaan binomikertoimeen tarvittava kerroin.
 $a = @_[0];
 $tulos = 1;
 for ($i = 1; $i <= $a; $i += 1){
  $tulos *= $i;

 }
 return $tulos
}

sub Todennakoisyys($$$$$$){
 #Otetaan syötteet.
 my $n = int @_[0];
 my $k = int @_[1];
 my $n_k = int @_[2];
 my $toistot = int @_[3];
 my $onnistumiset = int @_[4];
 my $tn = sprintf "%.5f", @_[5];

 #Lasketaan binomikerroin
 $binomi = $n/($k*$n_k);
 #Lasketaan todennäköisyys
 $tulos = $binomi*$tn**$onnistumiset*(1.0-$tn)**($toistot-$onnistumiset);

 return $tulos;
}

sub laske {
$lista->delete(0.0,'end');
 #Otetaan syöte, joka koostuu kolmesta osasta.
 @syote = split(',',$tlaatikko->get());

 $toistot = int $syote[0];
 $onnistumiset = int $syote[1];
 $tn = sprintf "%.5f", $syote[2];

 $summa = 0.0;
 #Lasketaan ensin, kun onnistumiset menevät tasan.

 #Lasketaan kertoimet.
 #Toistoa merkitään n:llä ja onnistumiset k:lla
 $n = Kertoma($toistot);
 $k = Kertoma($onnistumiset);
 $n_k = Kertoma($toistot-$onnistumiset);

 #Lasketaan binomitodenäköisyys.
 $tulos =  Todennakoisyys($n,$k,$n_k,$toistot,$onnistumiset,$tn);

 $lista->insert("end", "Tasan: $tulos");
 $summa += $tulos;

 #Sitten lasketaan, kun onnistumisia on vähintään tietty määrä.
 for ($x = 0; $x < $onnistumiset; $x+=1){

  #Lasketaan kertoimet.
  #Toistojen määrä pysyy samana, joten sen kerrointa ei tarvitse laskea.
  $k = Kertoma($x);
  $n_k = Kertoma($toistot-$x);

  #Lasketaan todennäköisyys.
  $tulos =  Todennakoisyys($n,$k,$n_k,$toistot,$x,$tn);


 $summa += $tulos;
 }
  $lista->insert("end", "Enintaan: $summa");
}

MainLoop;

jlaire [06.07.2021 00:09:42]

#

1) Perlissä kannattaa laittaa tiedoston alkuun vähintään use warnings; ja use strict;.

2) Toisin kuin monissa muissa skriptikielissä, Perlissä lokaalit muuttujat pitää esitellä my:llä. Muuten ne ovat globaaleja. Strict huomauttaa tästä.

3) Prototyyppien ($$$$$$) käyttöä ei ole aikoihin suositeltu.

4) Jos haluat ottaa @_ -taulukosta yhden arvon, oikea syntaksi on $_[0] eikä @_[0].

5) sub Todennakoisyys ottaa turhan monta parametriä. Olisi selkeämpää jättää 3 ensimmäistä pois ja laskea ne funktion sisällä. Tämä helpottaa funktion kutsumista ja poissulkee mahdollisia bugeja.

6) Yhden välilyönnin sisennys näyttää yhtä rumalta Perlissä kuin Pythonissakin, varsinkin kun koodissa on sisennysvirheitä. Käytä vähintään kahta tai neljää välilyöntiä pliis.

7) C-tyylisen for-silmukan sijaan for (1 .. $n) on usein siistimpi.

Alla vaihtoehtoinen toteutus parista funktiostasi.

#!/usr/bin/perl
use strict;
use warnings;
use v5.16;
no warnings "experimental::signatures";
use feature "signatures";

sub Kertoma($n) {
    my $tulos = 1;
    $tulos *= $_ for 1 .. $n;
    return $tulos;
}

sub Todennakoisyys($n, $k, $tn) {
    my $binomi = Kertoma($n) / (Kertoma($k) * Kertoma($n-$k));
    return $binomi * $tn**$k * (1-$tn)**($n-$k);
}

say Todennakoisyys(10, 4, 0.5);

Jere Sumell [06.07.2021 07:31:01]

#

jlaire kirjoitti:

6) Yhden välilyönnin sisennys näyttää yhtä rumalta Perlissä kuin Pythonissakin, varsinkin kun koodissa on sisennysvirheitä. Käytä vähintään kahta tai neljää välilyöntiä pliis.

Yleensä edistyneemmissä tekstieditoreissa, kuten Linuxin vim, tai Windows-ympäristossa toimivassa Notepad++ -editorissa saa määriteltyä asetuksista parametrilla sisennysvälin merkkikoon, joka on itselläni ainakin oletuksena pythonia ohjelmoidessa 4. En tiedä, mitä en käytä vimiä, vaan nanoa Linuxissa, niin siinähän ei käsittääkseni saa tuota sarkainväliä säädettyä millään parametrin asettamisella.

Antti Laaksonen [06.07.2021 19:54:05]

#

Jere Sumell kirjoitti:

En tiedä, mitä en käytä vimiä, vaan nanoa Linuxissa, niin siinähän ei käsittääkseni saa tuota sarkainväliä säädettyä millään parametrin asettamisella.

Nanossa asetuksia voi säätää tekemällä .nanorc-tiedoston. Pythonin koodaukseen voisi sopia jotain tällaista:

set autoindent
set tabsize 4
set tabstospaces

Jere Sumell [08.07.2021 09:36:47]

#

Kiitti Antti tuosta *rc -tiedoston luontivinkistä.

Mun mielestä tuon *rc tiedoston voi määritellä mille tahansa komennolle, ja sekin edesauttaa Linuxin mukautuvuutta juuri käyttäjän haluamaan tarpeeseen.

Aliakset on myos käteviä, jos on esimerkiksi usein toistuva grep -komennon ajomerkkijono, kun louhii tiedoston dataa, niin aliaksen luonti on kätevää.

Tuossahan voisi tehdä nanolle eri conffeilla noita aliaksia, esim nanoPy -alias voisi olla tuolla Antti sinun määrittelemälläsi start-upilla, ja mitä oli tuossa rekursio vai iteraatio kertoma -säikeessä juttua java.lang.StackOverFlow -errorista, mitä se heittää, niin joissain tilanteissa voisi olla kätevää tehdä javaStackSize -alias, jossa parametrina annettaisiin haluttu koko tuolle pinolle ohjelmaa suorittaessa. (Pinoasiat on siirretty kyseiseen keskusteluun.)

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta