Bashovo násobení a sčítání

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

Ahoj, potřebuji zjednodušený výraz pro třetí řádek, možná ten, který ano nepoužívat substituci příkazů.

Komentáře

  • @Theophrastus: Jak bylo navrženo, funguje to dobře, ale co když chci použít expr místo (()) .
  • Toto je bash a ne C, proto odeberte všechny ; – pokud jej nenapíšete do jednotného čísla.
  • Viz také: unix.stackexchange.com/q/40786/117549
  • declare -i a; for k in {0..49}; do a=2*$k+1; echo $a; done
  • Kromě: $(( ... )) je aritmetická expanze, nikoli substituce příkazů.

Odpověď

Použití aritmetické expanze:

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

Použití zastaralého expr nástroje:

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

Použití bc -l ( -l v tomto případě není skutečně potřeba, protože nejsou použity žádné matematické funkce):

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

Použití bc -l jako co-process (funguje jako druh výpočetní služby na pozadí¹):

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" 

Ten poslední vypadá (pravděpodobně) čistěji v 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" 

¹ To mi jednou vyřešilo problém, kdy jsem potřeboval zpracovat velké množství vstupů smyčka. Zpracování vyžadovalo několik výpočtů s plovoucí desetinnou čárkou, ale několikanásobné zobrazení bc ve smyčce se ukázalo být mimořádně pomalé. Ano, mohl jsem to vyřešit mnoha jinými způsoby, ale nudilo mě to …

Odpověď

Můžete to zjednodušit:

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

to:

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

Odpovědět

K vynucení výpočtu můžete použít příkaz let.

let a="2*k+1" 

Všimněte si, že v této struktuře nepotřebujeme $k; práci zvládne jednoduchý k.

Komentáře

  • To selže, pokud v aktuálním ' sa souboru s názvem a=2whateverk+1 Horší je, že pokud existuje ' sa soubor s názvem a=2+b[$(reboot)]k+1, který volá příkaz reboot . Nejlepší je použít ((...)) zde (((a = 2 * k + 1))) nebo syntaxi POSIX: a=$((2 * k + 1))
  • Můžeme to citovat; let a="2*k+1" abychom to vyřešili.

Odpověď

Aritmetické rozšíření, které pravděpodobně potřebujete, je toto:

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

Ve skutečnosti nemusíte používat proměnnou:

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

Nebo lze proměnnou počítání přesunout do for ((…)) smyčka:

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

pro smyčku ((…))

A v takovém případě může být také aritmetická expanze přesunuto do smyčky for:

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

Nebo získat všechny hodnoty v poli:

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

Žádný vzorec

Pravděpodobně nejkratší způsob, jak se vyhnout aritmetickému rozšíření, je zvýšit proměnnou dvakrát:

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

Nebo ještě jednodušší, stačí použít seq:

seq 1 2 100 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *