Bash multiplicación y suma

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

Hola, necesito una expresión simplificada para la tercera línea, tal vez una que sí no use la sustitución de comandos.

Comentarios

  • @Theophrastus: Como se sugirió, funciona bien, pero ¿y si quisiera usar expr en lugar de (()) .
  • Esto es bash y no C, así que elimine todas las ;: a menos que lo escriba en una línea singular.
  • Consulte también: unix.stackexchange.com/q/40786/117549
  • declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
  • Aparte: $(( ... )) es expansión aritmética, no sustitución de comandos.

Respuesta

Usando expansión aritmética:

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

Usando la anticuada utilidad expr:

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

Usando bc -l ( -l no es realmente necesario en este caso ya que no se usan funciones matemáticas):

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

Usando bc -l como coproceso (actúa como una especie de servicio de cálculo en segundo plano):

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" 

Ese último se ve (posiblemente) más limpio en 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" 

¹ Esto me resolvió un problema una vez en el que necesitaba procesar una gran cantidad de entrada en un bucle. El procesamiento requirió algunos cálculos de punto flotante, pero generar bc varias veces en el ciclo resultó ser extremadamente lento. Sí, podría haberlo resuelto de muchas otras formas, pero estaba aburrido …

Respuesta

Puedes simplificar:

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

para:

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

Responder

Puede usar el comando let para forzar un cálculo.

let a="2*k+1" 

Tenga en cuenta que no necesitamos $k en esta estructura; un k simple hará el trabajo.

Comentarios

  • Eso falla si hay ' un archivo llamado a=2whateverk+1 en el directorio. Peor aún, si hay ' un archivo llamado a=2+b[$(reboot)]k+1, que llama al comando reboot . Lo mejor es usar ((...)) aquí (((a = 2 * k + 1))), o la sintaxis POSIX: a=$((2 * k + 1))
  • Podemos citarlo; let a="2*k+1" para resolver eso.

Respuesta

La expansión aritmética que probablemente necesite es la siguiente:

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

De hecho, no necesita usar una variable:

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

O la variable de conteo podría moverse a un for ((…)) loop:

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

for ((…)) loop

Y, en ese caso, la expansión aritmética también podría ser movido al interior del bucle for:

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

O, para obtener todos los valores en una matriz:

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

Sin fórmula

Pero probablemente la forma más corta de evitar cualquier expansión aritmética es incrementar una variable dos veces:

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

O, incluso más simple, simplemente use seq:

seq 1 2 100 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *