LX-SCR-INFO-rekenen
updated 7/27/10 00:09

rekenen

In alle vorige hoofdstukken hebben we leren lezen en schrijven, sorteren, beslissen, repetitieve handelingen verrichten, zelfs orde en netheid hebben we geleerd. Aan rekenen zijn we echter nog niet toegekomen. We hebben dit item bewust tot het laatst gehouden.

Bash scripting is nu eenmaal geen rekenmachine zoals fortran, maar gewoon een uitbreiding van de command line interface. Bash is bijzonder geschikt voor systeembeheer, veel meer dan om het even welke programmeertaal, veel meer dan C en JAVA die universeel heten te zijn.

Toch moeten we af en toe rekenen, al was het maar een teller aanpassen, of de grootte van een schijf omzetten naar leesbare karakters.

We moeten ook getallen met elkaar kunnen vergelijken, om zo beslissingen te kunnen nemen in een if, een while of een case. Bovendien nemen we hier ook even de tijd om te kijken hoe je voorwaarden kunt ANDen of ORren.

Maar eerst nog dit: BASH rekent standaard alleen met INTEGERS
En ten tweede: er zijn veel manieren om hetzelfde te doen


  1. $(( )) of $[ ]

    deze syntax heeft geen probleem met spaties of dollartekens

    $ z=4
    $ z=$(( z+4 ))
    $ echo $z
    8

    zoals reeds gezegd: alleen operaties met gehele getallen zijn toegelaten:

    $ z=$(( z+3.5 ))
    bash: z+3.5 : syntax error: invalid arithmetic operator (error token is ".5 ")

    $ z=$(( z+5 ))
    $ echo $z
    17

    $ z=$(( z-9 ))
    $ echo $z
    8

    $ z=$(( z/3 ))
    $ echo $z
    2


    je kan de dubbele ((  ))
    vervangen door  [ ]


    $ z=$[ z+5 ]
    $ echo $z
    10

    $ z=$[z+5]
    $ echo $z
    15

    $ a=3
    $ b=8
    $ c=4
    $ z=$(( $a + $b - $c ))
    $ echo $z
    7

    $ z=$(( $a+$b-$c ))
    $ echo $z
    7

    $ z=$(($a+$b-$c))
    $ echo $z
    7

    $ z=$((a+b-c))
    $ echo $z
    7


    verkorte notering - pas op: werkt niet met [ ]:

    $ a=30
    $ (( a++ ))
    $ echo $a
    31

  2. let

    let aanvaardt geen enkele spatie, dollartekens moeten op de juiste plaats

    $ let a=12
    $ echo $a
    12

    $ let a=12-12
    $ echo $a
    0

    $ let a=12/2
    $ echo $a
    6

    $ a=5
    $ b=8
    $ c=17
    $ let a=$c/$a
    $ echo $a
    3

    $ let a=$c+$b
    $ echo $a
    25

    verkorte noteringen:

    $ let a++
    $ echo $a
    26

    $ let a+=1
    $ echo $a
    27


  3. Bewerkingen

    bewerking
    operator
    gebruik (( ))
    gebruik met let
    optelling
    +
    $((4 + 5))
    let x=4+5
    aftrekking
    -
    $[ 7 - 7 ]
    let x=7-7
    vermenigvuldiging
    *
    $((3 * 2))
    let x=3*2
    deling
    /
    $((6 / 3))
    let x=6/3
    modulo (rest)
    %
    $((8 % 7))
    let x=8%7
    machtsverheffing
    **
    $[ 2 ** 8 ]
    let x=2**8

  4. Bewerkingen met gelijkheidsteken

    operator
    bewerking met toewijzing
    gebruik betekenis
    = toewijzing
    a=b a=b
    *= vermenigvuldiging
    a*=b a=(a*b)
    /= deling
    a/=b a=(a/b)
    %= modulo (rest)
    a%=b a=(a%b)
    += optelling
    a+=b a=(a+b)
    -= aftrekking
    a-=b a=(a-b)
    <<= Bit-shift naar links a<<=b a=(a<<b)
    >>= Bit-shift naar rechts a>>=b a=(a>>b)
    &= Bitwise "and" a&=b a=(a&b)
    ^= Bitwise "exor" a^=b a=(a^b)
    |= Bitwise "or" a|=b a=(a|b)

  5. externe tool voor integers: /usr/bin/expr

    Spaties zijn verplicht met expr. expr is minder efficient dan let en (( )) want expr is een extern commando en start dus een subproces. Dat is in de huidige MultiCore computer helemaal niet erg voor een paar bewerkingen, maar voor enkele duizenden achter mekaar via lussen of functions, is expr toch minder efficient.


    syntax:

    expr <waarde1> <operator> <waarde2>

    of

    var=`expr <waarde1> <operator> <waarde2>`
    var=$(expr <waarde1> <operator> <waarde2>)

    De operatoren zijn dezelfde als voor let of (( ))

    enkele voorbeelden

    `expr`    
    z=`expr $z + 3`
    $(expr)    z=$(expr $z + 3)

    $ a=$(expr 1 + 3)
    $ b=$(expr 2 - 1)
    $ c=$(expr 10 / 2)
    $ d=$(expr 20 % 3)
    $ e=$(expr 10 \* 3)
    $ f=`expr 6 + 3`

    $ g=$(expr $a \* $c)
    $ echo $a $b $c $d $e $f $g
    4 1 5 2 30 9 20

    Let op, de vermenigvuldiging moet voorafgegaan worden door de \ omdat * wordt gezien als een wildcard.

  6. externe tool voor reals: /usr/bin/bc

    interactief:

    $ bc
    bc 1.06.94
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'.

    17 / 7
    2
    quit

    $ bc
    bc 1.06.94
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'.

    scale=3
    17 / 7

    2.428
    quit

    In het eerste voorbeeld hebben we de commando's in vetjes ingetikt. (bc, 17/7 en quit) Als resultaat kregen 2.

    In het tweede voorbeeld hebben we vooraleer te rekenen scale=3 ingetikt.
    Het gevolg is dat het resultaat op 3 cijfers nauwkeurig werd berekend.

    via een pipe:

    $ echo "scale=5; 17/7" | bc
    2.42857

    in een script:


    a=$(echo "scale=10; 17/7" | bc)
    echo $a

    2.4285714285

    of ook

    pi=$(echo "scale=10; 4*a(1)" | bc -l)
    echo $pi

    3.1415926532

    :-)

    http://linux.about.com/od/commands/l/blcmdl1_bc.htm

  7. links

    http://www.softpanorama.org/Scripting/Shellorama/arithmetic_expressions.shtml
    http://hacktux.com/bash/math
    http://www.linuxconfig.org/Bash_scripting_Tutorial
    http://www.freeos.com/guides/lsst/ch02sec07.html
    http://dsl.org/cookbook/cookbook_35.html#SEC480