Multiplication et addition de Bash

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

Salut, j'ai besoin d'une expression simplifiée pour la troisième ligne, peut-être une qui n'utilise pas de substitution de commande.

AVS
la source
@Theophrastus: Comme suggéré, cela fonctionne bien, mais si je voulais utiliser expr au lieu de (()).
AVS
Ce n'est bashpas le cas C, alors supprimez tout ;- sauf si vous l'écrivez sur une ligne singulière.
ott--
Voir aussi: 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
À part: $(( ... ))l'expansion arithmétique n'est pas une substitution de commande.
dave_thompson_085

Réponses:

27

Utilisation de l'expansion arithmétique:

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

Utilisation de l' exprutilitaire désuet :

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

Utilisation bc -l( -lpas réellement nécessaire dans ce cas car aucune fonction mathématique n'est utilisée):

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

Utilisé bc -lcomme un co-processus (il agit comme une sorte de service de calcul en arrière-plan¹):

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"

Ce dernier semble (sans doute) plus propre dans 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"

¹ Cela a résolu un problème pour moi une fois où je devais traiter une grande quantité d'entrée en boucle. Le traitement a nécessité quelques calculs en virgule flottante, mais le frai bcplusieurs fois dans la boucle s'est avéré extrêmement lent. Oui, j'aurais pu le résoudre de bien d'autres façons, mais je m'ennuyais ...

Kusalananda
la source
12

Vous pouvez simplifier:

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

à:

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

Vous pouvez utiliser la letcommande pour forcer un calcul.

let a="2*k+1"

Notez que nous n'avons pas besoin $kde cette structure; un simple kfera le travail.

Stephen Harris
la source
4
Cela échoue s'il y a un fichier appelé a=2whateverk+1dans le répertoire courant. Pire, s'il y a un fichier appelé a=2+b[$(reboot)]k+1, qui appelle la rebootcommande. Le mieux est d'utiliser ((...))ici ( ((a = 2 * k + 1))), ou la syntaxe POSIX:a=$((2 * k + 1))
Stéphane Chazelas
Nous pouvons le citer; let a="2*k+1"pour résoudre ça.
Stephen Harris
2

L'expansion arithmétique dont vous avez probablement besoin est la suivante:

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

En fait, vous n'avez pas besoin d'utiliser une variable:

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

Ou la variable de comptage pourrait être déplacée dans une for ((…))boucle:

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

pour ((…)) boucle

Et, dans ce cas, l'expansion arithmétique pourrait également être déplacée à l'intérieur de la boucle for:

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

Ou, pour obtenir toutes les valeurs d'un tableau:

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

Pas de formule

Mais probablement le moyen le plus court d'éviter toute expansion arithmétique est d'incrémenter une variable deux fois:

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

Ou, encore plus simple, utilisez simplement seq:

seq 1 2 100

la source