next up previous contents
Nästa: 12. Avancerad Bashprogrammering Upp: 11. Grundläggande Bashprogrammering Förra: 11.6 Strängoperatorer

11.7 Aritmetik

Ordet ''aritmetik'' betyder helt enkelt räkning. I detta avsnitt beskrivs det hur man kan utföra enklare beräkningar med hjälp av Bash.

Ett uttryck av formen $((formel)) skrivs om till det uträknade värdet av formel. Formlerna som beräknas får bland annat innehålla de fyra vanliga räknesätten, som skrivs med operatorerna + (addition), - (subtraktion), * (multiplikation) och / (division).$ echo $((17+23))
40
$ mkdir Kapitel$((17+23))A
$ ls
Kapitel40A/          kopia.980217.bellman
bellman               lenngren
$
Ingen beräkning sker ifall tecknen $(( och )) utelämnas:$ echo 17+23
17+23
$
Man får också använda variabler:$ x=17; y=23
$ echo $((x+y))
40
$
Lägg märke till att man inte behöver skriva dollartecken före variablernas namn när de som ovan förekommer i en beräkning.

Med hjälp av while kan man låta en variabel genomlöpa en följd av tal, som programmet loop nedan visar.

#!/bin/bash
i=5
while [ $i -le 10 ]
do
  echo "Nu har 'i' värdet $i"
  i=$((i+1))
done

Utskriften från loop ser ut så här:$ loop
Nu har 'i' värdet 5
Nu har 'i' värdet 6
Nu har 'i' värdet 7
Nu har 'i' värdet 8
Nu har 'i' värdet 9
Nu har 'i' värdet 10
$

Multiplikationen i formeln 2+3*4 utförs före additionen eftersom det är en konvention att multiplikation och division har högre prioritet än addition och subtraktion. Om man vill att additionen ska utföras först måste man ange parenteser, (2+3)*4=20.$ echo Man räknar lätt ut att 2+3*4=$((2+3*4))
Man räknar lätt ut att 2+3*4=14
$ echo $(( (2+3)*4 ))
20
$

En förteckning av de operatorer som kan användas vid beräkningar i Bash ges i tabell 11.6. Operatorerna är grupperade i prioritetsordning.


 
Tabell 11.6: De aritmetiska operatorerna.
 
Operator Typ
+ - unär
! ~ unär
* / % binär
+ - binär
<< >> binär
< <= > >= binär
== != binär
& binär
^ binär
| binär
&& binär
|| binär
?...: ternär
= += -= *= /= %= <<= >>= &= |= ^= binär

Bash räknar bara med heltal. Detta innebär i synnerhet att om resultatet vid en division inte går jämnt ut, så stryks decimalerna från svaret. Till exempel gäller i Bash att 13/5 är lika med 2. Om 13 hästar ska delas ut till fem systrar, så får systrarna två hästar var. Kvoten är därmed 2. Det blir tre hästar över, och man säger att resten (dvs det antal som blev över) är 3.$ echo $(( 13/5 ))
2
$
Resten vid en division kan beräknas med hjälp av operatorn %.$ echo $(( 13%5 ))
3
$

Bash kan bara hantera heltal av en begränsad storlek; vanligtvis får talen ha högst 9-10 siffror om resultatet ska bli rätt.$ echo $(( 1000*1000 ))
1000000
$ echo $(( 1000000*1000000 ))
-727379968
$
Det korrekta resultatet vid den andra beräkningen ovan är ett tal med 13 siffror, men eftersom Bash (på min dator) inte kan hantera så stora tal gavs ett fullständigt felaktigt resultat.

Om man omger ett heltal med tecknen (( respektive )), så undersöker Bash ifall talet är skilt från noll. Lyckad slutstatus anger att talet var skilt från noll, misslyckad slutstatus att talet var lika med noll.$ (( 5 ))
$ echo $?
0
$ (( 2*3-6 ))
$ echo $?
1
$
Som vi snart ska se kan detta användas som ett alternativ till kommandot test vid jämförelser av heltal.


 
Tabell: Jämförelser.
 
Jämförelse  Uppfylld om...
tal1 < tal2   tal1 är mindre än tal2
tal1 <= tal2   tal1 är mindre än eller lika med tal2
tal1 == tal2   tal1 är lika med tal2
tal1 != tal2   tal1 inte är lika med tal2
tal1 >= tal2   tal1 är större än eller lika med tal2
tal1 > tal2   tal1 är större än tal2

Tabell 11.7 visar hur man kan jämföra två heltal i Bash. Lägg särskilt märke till att likhet skrivs med två likhetstecken eftersom det annars skulle bli en tilldelning. Resultatet av en jämförelse är ett heltal, nämligen 1 (som betyder ''sant'') ifall jämförelsen var uppfylld, annars 0 (dvs ''falskt''). Jämförelsen a==b betraktas alltså som en beräkning vars värde är 1 ifall a=b; värdet är 0 om $a\neq b$.$ echo $(( 5>3 ))
1
$ echo $(( 2*4>=9 ))
0
$
Om man utelämnar dollartecknen ovan, så får man tester i stället för beräkningar:$ if (( 1+1==2 )) ; then echo 'Bash kan räkna!' ; fi
Bash kan räkna!
$

Variabeln RANDOM, som är inbyggd i Bash, ger ett slumptal mellan 0 och 32767.$ echo $RANDOM
12281
$ echo $RANDOM
31550
$ echo $RANDOM
3487
$
Om vi vill ha ett slumptal mellan tex 0 och 100, så kan vi först låta Bash ge oss ett slumptal mellan 0 och 32767, och sedan ta resten vid division av detta tal med 101:$ echo $(( $RANDOM%101 ))
37
$
För att simulera ett tärningskast behöver vi ett slumptal mellan 1 och 6. Vi beräknar då först ett slumptal mellan 0 och 5, och adderar sedan 1 till detta:$ echo $(( $RANDOM%6+1 ))
4
$
Programmet räkna nedan beräknar två slumptal mellan 1 och 10. Programmet frågar efter summan, och det ger sig inte förrän man har svarat rätt.  

#!/bin/bash
TAL1=$(( $RANDOM%10+1 ))
TAL2=$(( $RANDOM%10+1 ))
read -p "Vad är $TAL1+$TAL2? " SVAR
until (( SVAR == TAL1+TAL2 ))
do
  echo 'Fel fel fel!'
  read -p "Ange $TAL1+$TAL2 igen: " SVAR
done
echo 'Rätt svar!'

Om det svar man matar in är fel, så skrivs texten ''Fel fel fel!'' ut, och man får sedan göra ett nytt försök.$ räkna
Vad är 5+7? 8
Fel fel fel!
Ange 5+7 igen: 12
Rätt svar!
$ räkna
Vad är 1+1? 2
Rätt svar!
$
Vid den andra körningen fick vi ett lätt problem, 1+1, och lyckades därmed svara rätt första gången. Därför kördes aldrig kommandona mellan do och done.

Instruktionen declare -i namn anger att variabeln namn är ett heltal. Fördelen med detta är att värdet av namn då beräknas automatiskt, dvs även om tecknen $(( och )) utelämnas. I följande program, som visar ännu ett sätt att låta en heltalsvariabel genomlöpa ett antal värden, har en variabel markerats som heltal:

#!/bin/bash
declare -i tal=1
echo -n 'Några tal:'
while (( tal<=10 )) ; do
  echo -n " $tal"
  tal=tal+1
done
echo '.'

Utskriften från programmet blir

Några tal: 1 2 3 4 5 6 7 8 9 10.

Operatorn += är en kombination av addition och tilldelning. Till exempel har a+=3 värdet a+3, och som en sidoeffekt av beräkningen a+=3 får a värdet a+3. Operatorerna -=, *= osv fungerar på motsvarande sätt. Programmet ovan kan alltså skrivas så här istället:

#!/bin/bash
declare -i tal=0
echo -n 'Några tal:'
while (( (tal+=1)<=10 )) ; do
  echo -n " $tal"
done
echo '.'

Oftast är den förra versionen av programmet att föredra eftersom den senare versionen är mer svårläst.


next up previous contents
Nästa: 12. Avancerad Bashprogrammering Upp: 11. Grundläggande Bashprogrammering Förra: 11.6 Strängoperatorer
Goran Andersson
1999-03-08