2009-12-04 19 views
6

Sono abbastanza nuovo nello script di bash e di solito evito tutto, ma ho bisogno di scrivere uno script bash per eseguire alcune cose semplici su un cluster remoto. Sto avendo problemi con un ciclo for che fa quanto segue:Semplici istruzioni matematiche in bash in un ciclo for

for i in {1..20} 
do 
    for j in {1..20} 
    do 
     echo (i*i + j*j) **.5 <--- Pseudo code! 
    done 
done 

Potete aiutarmi con questa semplice matematica? Ho lanciato $ ovunque e non riesco a scriverlo correttamente. Se potessi aiutarmi a capire come le variabili sono denominate/assegnate in bash per i loop e le limitazioni dell'interpretazione di bash in matematica (come si fa la radice quadrata?) Sarei molto grato. Grazie!

risposta

8

Ecco una soluzione decente:

for i in {1..20} 
do 
    for j in {1..20} 
    do 
     echo "scale = 3; sqrt($i*$i + $j*$j)" | bc 
    done 
done 

uscita sarà:

1.414 
2.236 
3.162 
2.236 
[...etc...] 
0

Utilizzare il doppio paren per valutare una variabile.

variabileA = $ ((* variabileB variableC))

Solo per interi però.

0

In genere si utilizza $ ((1 * 3)), ma il tuo caso non funzionerà in quanto bash non supporta i numeri in virgola mobile. Dovrai utilizzare uno strumento esterno come awk, bc o dc: http://mywiki.wooledge.org/BashFAQ/022

2

La matematica della shell può essere eseguita in diversi modi.

echo $((i*i + j*j)) 
echo $[ i*i + j*j ] 
expr "$i" '*' "$i" '+' "$j" '*' "$j" 

Tuttavia, questo può gestire solo l'aritmetica dei numeri interi. Invece, è possibile utilizzare bc:

echo "scale = 5; sqrt($i*$i + $j*$j)" | bc 

Modifica scale al numero di cifre decimali desiderati.

+0

sto diventando davvero tanti (standard_in) 1: Errore di analisi – physicsmichael

+0

Probabilmente stai manca il ' ..' tra il tuo 1 e il tuo 20 nella tua gamma {1..20} – dustmachine

+0

Strano, dovrebbe funzionare in qualsiasi POSIX 'bc'. Cosa succede se usi 'dc'? ad esempio 'dc -e" 5 k $ i $ i * $ j $ j * + v p "' – ephemient

9

espansione aritmetica bisogno $((...)) notazione, in modo da qualcosa come:

echo $((i*i + j*j)) 

Tuttavia, bash utilizza solo numeri interi quindi potrebbe essere necessario utilizzare uno strumento esterno come dc.

E.g.

dc -e "18k $i $i * $j $j * + v p" 
0

Il codice

echo $[(($i * $i) + ($j * $j)) ** $X] 

funziona se $X è un numero intero. Stai provando a prendere la radice quadrata, e non sono sicuro che l'aritmetica incorporata di bash lo farà. Probabilmente starai meglio usando uno strumento di calcolo più potente (come bc, ecc.) Per questo.

2
#!/bin/bash 
for i in {1..20}; do 
    for j in {1..20}; do 
     echo 5k$i $i\* $j $j\*+vp | dc 
    done 
done 
+0

La mia variante: 'printf"% s% s 10kd * rd * + vp "" $ i "" $ j "| dc' –

0

Bash non offre funzioni matematiche. Tuttavia, quasi sicuramente hai la shell Korn installata.Questo dovrebbe funzionare:

#!/bin/ksh 

for i in {1..20} 
do 
    for j in {1..20} 
    do 
     x=$((sqrt(i*i + j*j))) 
     echo "sqrt($i^2 + $j^2) = $x" 
    done 
done 

L'inizio della produzione è

sqrt(1^2 + 1^2) = 1.41421356237309505 
sqrt(1^2 + 2^2) = 2.2360679774997897 
sqrt(1^2 + 3^2) = 3.16227766016837933 
sqrt(1^2 + 4^2) = 4.12310562561766055 
sqrt(1^2 + 5^2) = 5.09901951359278483 
sqrt(1^2 + 6^2) = 6.08276253029821969 
sqrt(1^2 + 7^2) = 7.07106781186547524 
sqrt(1^2 + 8^2) = 8.06225774829854965 
sqrt(1^2 + 9^2) = 9.05538513813741663 
sqrt(1^2 + 10^2) = 10.0498756211208903 
+0

"quasi certamente"? Certamente non è standard su nessuna distribuzione Linux che abbia mai visto. Forse intendi * BSD? – ephemient

+0

Mac OSX 10.6 ce l'ha. – physicsmichael

+0

OSX è simile a BSD. –

-1

Un'altra forma di espressioni matematiche interi in Bash mette le doppie parentesi sulla parte esterna del l'intera espressione per le operazioni di assegnazione:

((var = i ** 2)) 
((i++)) 
((position += delta)) 

Come si può vedere, i simboli del dollaro non sono necessari qui (né all'interno di $(())). Inoltre, gli spazi sono consentiti attorno al segno di uguale.

Inoltre, questa forma può essere utilizzato in condizionali:

sixpacks=8    # note spaces not allowed here 
((beerprice = 8)) # but you can use spaces this way 
budget=50 

# you can do assignments inside a conditional just like C 
until ((((beertotal = sixpacks * beerprice)) <= budget)) 
do 
    ((sixpacks--)) 
done 
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}." 

Oppure si può sostituire tutto questo con questo, naturalmente:

beerprice=8 
budget=50 

# integer division 
((sixpacks = budget/beerprice)) 
((beertotal = sixpacks * beerprice)) 
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}." 

Bash ha anche un let dichiarazione:

let a=2**16 
let 'a>>=1' # bitwise shift - some operations need to be quoted or escaped 
((a>>=1)) # but not inside (()) 
1

il cluster remoto ha solo bash? in caso contrario, provare e vedere se avete awk

awk 'BEGIN{ 
    for(i=1;i<=20;i++){ 
    for(j=1;j<=20;j++){ 
     print (i*i + j*j) ** 0.5 
    } 
    } 
}' 
0

con zsh, questo funzionerà

for i in {1..20};do 
    for j in {1..20};do 
    echo $((($i*$i + $j*$j)**.5)) 
    done 
done