Bash multiplicación y suma


18
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 no use la sustitución de comandos.


@Theophrastus: Como se sugirió, funciona bien, pero ¿y si quisiera usar expr en lugar de (())?
AVS

Esto es bashy no C, así que elimine todo ;, a menos que lo escriba en una línea singular.
ott--


declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
Cyrus

1
Aparte: $(( ... ))es la expansión aritmética, no la sustitución de comandos.
dave_thompson_085

Respuestas:


27

Usando la expansión aritmética:

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

Usando la exprutilidad anticuada :

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

Uso bc -l(en -lrealidad no es necesario en este caso, ya que no se utilizan funciones matemáticas):

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

Utilizando bc -lcomo un coproceso (actúa como una especie de servicio de computación 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 resolvió un problema para mí una vez donde necesitaba procesar una gran cantidad de entrada en un bucle. El procesamiento requirió algunos cálculos de coma flotante, pero el desove bcalgunas veces en el ciclo resultó ser extremadamente lento. Sí, podría haberlo resuelto de muchas otras maneras, pero estaba aburrido ...



5

Puede usar el letcomando para forzar un cálculo.

let a="2*k+1"

Tenga en cuenta que no necesitamos $ken esta estructura; Un simple khará el trabajo.


44
Eso falla si hay un archivo llamado a=2whateverk+1en el directorio actual. Peor aún, si hay un archivo llamado a=2+b[$(reboot)]k+1, eso llama al rebootcomando. Lo mejor es usar ((...))aquí ( ((a = 2 * k + 1))), o la sintaxis POSIX:a=$((2 * k + 1))
Stéphane Chazelas

Podemos citarlo; let a="2*k+1"para resolver eso
Stephen Harris

2

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

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 ((…))ciclo:

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

en bucle

Y, en ese caso, la expansión aritmética también podría moverse dentro del ciclo 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 formula

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.