Bash Multiplikation und Addition

15
for k in {0..49};
do
a=$(($((2*$k))+1));
echo $a;
done

Hallo, ich brauche einen vereinfachten Ausdruck für die dritte Zeile, vielleicht einen, der keine Befehlsersetzung verwendet.

AVS
quelle
@Theophrastus: Wie vorgeschlagen funktioniert es gut, aber was ist, wenn ich expr anstelle von (()) verwenden wollte.
AVS
Dies ist bashund nicht C, also entfernen Sie alle ;- es sei denn, Sie schreiben es in einer einzelnen Zeile.
ott--
Siehe auch: unix.stackexchange.com/q/40786/117549
Jeff Schaller
declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
Cyrus
1
Nebenbei: Ist die $(( ... ))arithmetische Erweiterung keine Befehlssubstitution?
Dave_thompson_085

Antworten:

25

Verwenden der arithmetischen Erweiterung:

for (( k = 0; k < 50; ++k )); do
  a=$(( 2*k + 1 ))
  echo "$a"
done

Verwenden des antiquierten exprDienstprogramms:

for (( k = 0; k < 50; ++k )); do
  a=$( expr 2 '*' "$k" + 1 )
  echo "$a"
done

Using bc -l(wird -lin diesem Fall nicht benötigt, da keine mathematischen Funktionen verwendet werden):

for (( k = 0; k < 50; ++k )); do
  a=$( bc -l <<<"2*$k + 1" )
  echo "$a"
done

Verwendung bc -lals Co-Prozess (wirkt wie eine Art Rechendienst im Hintergrund¹):

coproc bc -l

for (( k = 0; k < 50; ++k )); do
  printf "2*%d + 1\n" "$k" >&${COPROC[1]}
  read -u "${COPROC[0]}" a
  echo "$a"
done

kill "$COPROC_PID"

Das letzte sieht (wohl) sauberer aus in ksh93:

bc -l |&
bc_pid="$!"

for (( k = 0; k < 50; ++k )); do
  print -p "2*$k + 1"
  read -p a
  print "$a"
done

kill "$bc_pid"

¹ Dies löste ein Problem für mich, bei dem ich eine große Menge an Eingaben in einer Schleife verarbeiten musste. Die Verarbeitung erforderte einige Gleitkommaberechnungen, aber bceinige Male in der Schleife zu spawnen, erwies sich als außerordentlich langsam. Ja, ich hätte es auf viele andere Arten lösen können, aber mir war langweilig ...

Kusalananda
quelle
10

Sie können vereinfachen:

a=$(($((2*$k))+1));

zu:

a=$((2*k+1))
Jeff Schaller
quelle
5

Mit dem letBefehl können Sie eine Berechnung erzwingen.

let a="2*k+1"

Beachten Sie, dass wir $kin dieser Struktur nicht brauchen ; Ein einfacher kwird die Arbeit erledigen.

Stephen Harris
quelle
4
Das schlägt fehl, wenn a=2whateverk+1im aktuellen Verzeichnis eine Datei aufgerufen wird . Schlimmer noch, wenn eine Datei aufgerufen a=2+b[$(reboot)]k+1wird, die den rebootBefehl aufruft . Am besten ist es zu verwenden , ((...))hier ( ((a = 2 * k + 1))) oder die POSIX - Syntax:a=$((2 * k + 1))
Stéphane Chazelas
Wir können es zitieren; let a="2*k+1"um das zu lösen.
Stephen Harris
2

Die arithmetische Erweiterung, die Sie wahrscheinlich benötigen, ist folgende:

a=$(( 1+2*k ))

Tatsächlich müssen Sie keine Variable verwenden:

for k in {0..49}; do
    echo "$(( 1 + 2*k ))"
done

Oder die Zählvariable könnte in eine for ((…))Schleife verschoben werden :

for (( k=0;k<50;k++ )); do
    a=$(( 1+2*k ))
    printf '%s\n' "$a"
done

für ((…)) Schleife

In diesem Fall könnte die arithmetische Erweiterung auch in die for-Schleife verschoben werden:

for (( k=0 ; a=1+2*k , k<50 ;  k++)); do
    printf '%s\n' "$a"
done

Oder, um alle Werte in einem Array abzurufen:

for (( k=0 ; a[k]=1+2*k , k<49 ;  k++ )); do :; done
printf '%s\n' "${a[@]}"

Keine Formel

Der wahrscheinlich kürzeste Weg, um eine arithmetische Erweiterung zu vermeiden, besteht darin, eine Variable zweimal zu erhöhen:

for (( k=0,a=1 ; k<50 ;  k++,a++,a++ )); do
    printf '%s\n' "$a"
done

Oder, noch einfacher, benutze einfach seq:

seq 1 2 100

quelle