Kirjoittaja Aihe: Ohjeita shell-skriptaukseen (bash)  (Luettu 621452 kertaa)

petteriIII

  • Käyttäjä
  • Viestejä: 705
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #340 : tänään kello 13:36 »
Tässä on 16 numeroinen neliöjuuri-laskun tarvitsema summaaja-vähentäjä. Aluksi tehdään versio joka toimii ainoastaan kokonaisluvuilla ja vasta pitkien testauksien jälkeen sitä voi alkaa sovittamaan desimaaliluvuille. Inhottavan näköistä koodia siinä on paljon - mutta BASH:iksi se on kuitenkin hyvin nopea vaikkakin muiden kielien kannalta todella hidas - tämä funktio vie aikaa alle millisekunnin - ja bc tai awk:kin kuluttaa aikaa 2-3 millisekuntia samaan laskuun - se 3ms kestää ennenkuin ne aloivat toimia.

BASH:in toiminnan tarkoitus on opettaa muunmuassa kuinka vaikeita alkeis-tehtävätkin ovat ratkaista siten että ne toimisivat aina moitteettomasti - ja nehän ovat samat kaikissa kielissä. Ja jokainen kieli on samojen matematiikan sääntöjen sitoma ja kaikki ratkaisevat tämmöisiä olemattoman kokoisia tehtäviä sammallatavoin - muut kielet tosin ratkovat ne kirjastojensa sokkeloissa ja prosessoriensa langoituksessa - joten varmaankaan et ole noita ratkaisuja nähnytkään. Mutta riittää kun tietää että niitä on.

- eihän matematiikkaa voi millään kielellä toteuttaa moitteettomasti kokonaan vaan aina tulee tilanteita joissa nikotellaan. Ja koska BASH:in on valehdeltu olevan täysin kykenemätön mihinkään eikä ole tehty ohjelmia alkeis-ongelmia ratkomaan niin että kun BASH alkaa nyt siitä missä toiset kielet olivat yli kolmekymmentä vuotta sitten niin BASH nikottelee alkuunsa ihan kaikissa tehtävissä. Mutta se hyvä puoli näissä ohjelmallisissa ratkaisuissa on että vaikka ne ovat todella hitaita niin kaiken saa lopulta toimimaan.

- kielen toiminnassa arvostetaan usein joustavuutta nopeutta enemmän - joten jos kielen perusteet ovat kunnossa niin joustavampi voittaa ilmanmuuta - ja vanhoilla käskyillä BASH on erittäin joustava - ja siitähän se riemu repesi sillä sellaista ei voi sallia että harrastelijan työkalu olisi parempi kuin ammattilaisella joten BASH:in vanhemmat veivät lapseltaan hampaat. Onneksi he eivät uskaltaneet kajota tulkkiin ja vanhat käskyt ovat tulkissa.
 
Pikku-tehtävistä tämä oli ehdottomasti elämäni työläin tehtävä - koska en kuunnellut omia puheitani siitä että vähennyslasku käsitellään ensimmäisenä - silloinkin kun toiminnan aikana saattaa jostain väli-tuloksesta tulla negatiivinen:
Koodia: [Valitse]
function summaa36 () { # ensimmäisen luvun tulee olla positiivinen ja suurempi mutta toinen pienempi luku voi olla negatiivinenkin

tulosta=: # yhdessä paikassa päätetään tulostetaanko skriptissä välituloksia missään. Vaihtoehdot:tulosta=echo ja tulosta=: . : on käsky olla tekemättä  mitään ja kuitenkin sillä voi olla parametreja aivan niinkuin echo:llakin.

luku1=$1
luku2=$2
[[ ${1:0:1} = - ]]  && merkki1=- || merkki1='+'
[[ ${2:0:1} = - ]]  && merkki2=- || merkki2='+'
luku1=${luku1//\-/}; luku2=${luku2//\-/} # poistetaan merkki -

luku1="0000000000000000000000000000000000000"$luku1; luku1=${luku1: -36:36}
luku2="0000000000000000000000000000000000000"$luku2; luku2=${luku2: -36:36}   

luku11=${luku1:0:18}; luku12=${luku1:18:18} #; [[ $luku11 -eq 0 ]] && luku11=0
luku21=${luku2:0:18}; luku22=${luku2:18:18} #; [[ $luku22 -eq 0 ]] && luku22=0                             
$tulosta annettu_luku           18_ensimmäistä_numeroa     18_viimeistä_numeroa
$tulosta $luku1 $luku11    $luku12 
$tulosta $luku2 $luku21    $luku22

alivuoto=0; ylivuoto=0
apu1=$((10#$luku12$merkki2 10#$luku22))
# [[ ${#apu1} -eq 19 ]] && { apu1=${apu1:0:18}; ylivuoto=1 ;} ; [[ $apu1 -lt 0 ]] && { apu1=$(($apu1+"100000000000000000")); alivuoto=1 ;}  # epäilyttävä
[[ $apu1 -lt 0 ]] && { apu1=$(($apu1+"1000000000000000000")); alivuoto=1 ;}; [[ ${#apu1} -eq 19 ]] && { apu1=${apu1:1:19}; ylivuoto=1 ;} ;   # epäilyttävä
apu1="000000000000000000000"${apu1#[-+]}; apu1=${apu1: -18:18}; $tulosta vähemmän merkitsevien lukujen summa: $apu1
apu2=$((10#$luku11$merkki2 10#$luku21+$ylivuoto-$alivuoto)); $tulosta enemmän merkitsevien lukujen summa: $apu2 ylivuoto: $ylivuoto alivuoto: $alivuoto

apu=$apu2${apu1#0}; echo ${apu##+(0)} ;}

# esimerkkilaskuja:
echo -e '\n\n'; time summaa36 22222222222222211111111111111111 2222222299999999999922222222221   
echo -e '\n\n'; time summaa36 22222222222222211111111111111111 -2222222299999999999922222222221
echo -e '\n\n'; time summaa36 555 -6
echo -e '\n\n'; time summaa36 555 6

-tulokset voi tarkistaa vaikka bc-llä esimerkiksi käskyllä: bc<<<"22222222222222211111111111111111+2222222299999999999922222222221"