Простые математические выражения в bash в цикле for - PullRequest
6 голосов
/ 05 декабря 2009

Я довольно новичок в написании сценариев bash и обычно избегаю всего этого, но мне нужно написать сценарий bash, чтобы выполнить некоторые простые вещи на удаленном кластере. У меня проблемы с циклом for, который выполняет следующие действия:

for i in {1..20}
do
    for j in {1..20}
    do
        echo (i*i + j*j ) **.5  <--- Pseudo code!
    done
done

Можете ли вы помочь мне с этой простой математикой? Я бросил $ везде и не могу написать это правильно. Если бы вы могли помочь мне понять, как переменные называются / присваиваются в bash для циклов и ограничениях интерпретации bash math (как вы делаете квадратный корень?), Я был бы очень благодарен. Спасибо!

Ответы [ 11 ]

11 голосов
/ 05 декабря 2009

Арифметическому расширению нужна $((...)) запись, поэтому что-то вроде:

echo $((i*i + j*j))

Однако bash использует только целые числа, поэтому вам может потребоваться использовать внешний инструмент, такой как dc.

1007 * Е.Г. *

dc -e "18k $i $i * $j $j * + v p"
8 голосов
/ 05 декабря 2009

Вот достойное решение:

for i in {1..20}
do
   for j in {1..20}
   do
       echo "scale = 3; sqrt($i*$i + $j*$j)" | bc
   done
done

Вывод будет:

1.414
2.236
3.162
2.236
[...etc...]
2 голосов
/ 05 декабря 2009
#!/bin/bash
for i in {1..20}; do
    for j in {1..20}; do
        echo 5k$i $i\* $j $j\*+vp | dc
    done
done
2 голосов
/ 05 декабря 2009

Shell математика может быть сделано несколькими способами.

echo $(( i*i + j*j ))
echo $[ i*i + j*j ]
expr "$i" '*' "$i" '+' "$j" '*' "$j"

Однако, это может обрабатывать только целочисленную арифметику. Вместо этого вы можете использовать bc:

echo "scale = 5; sqrt( $i*$i + $j*$j)" | bc

Измените scale на желаемое количество десятичных знаков.

1 голос
/ 07 декабря 2009

в вашем удаленном кластере есть только bash? если нет, попробуйте и посмотрите, есть ли у вас awk

awk 'BEGIN{
  for(i=1;i<=20;i++){
    for(j=1;j<=20;j++){
       print ( i*i + j*j ) ** 0.5
    }
  }
}'
0 голосов
/ 12 июля 2012

с Zsh, это будет работать

for i in {1..20};do
  for j in {1..20};do
     echo $((($i*$i + $j*$j)**.5))
  done
done
0 голосов
/ 05 декабря 2009

Другая форма целочисленных математических выражений в Bash помещает двойные скобки снаружи всего выражения для операций присваивания:

(( var = i ** 2 ))
(( i++ ))
(( position += delta ))

Как видите, знаки доллара здесь не нужны (ни внутри $(())). Также разрешены пробелы вокруг знака равенства.

Также эту форму можно использовать в условных выражениях:

sixpacks=8             # note spaces not allowed here
(( beerprice = 8 ))    # but you can use spaces this way
budget=50

# you can do assignments inside a conditional just like C
until (( (( beertotal = sixpacks * beerprice )) <= budget ))
do
    (( sixpacks-- ))
done
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}."

Или вы можете заменить все это на это, конечно:

beerprice=8
budget=50

# integer division
(( sixpacks = budget / beerprice ))
(( beertotal = sixpacks * beerprice ))
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}."

Bash также имеет выражение let:

let a=2**16
let 'a>>=1'    # bitwise shift - some operations need to be quoted or escaped
(( a>>=1 ))    # but not inside (())
0 голосов
/ 05 декабря 2009

Bash не предлагает математических функций. Однако у вас почти наверняка установлена ​​оболочка korn. Это должно работать:

#!/bin/ksh

for i in {1..20}
do
    for j in {1..20}
    do
        x=$((sqrt(i*i + j*j)))
        echo "sqrt($i^2 + $j^2) = $x"
    done
done

Начало вывода

sqrt(1^2 + 1^2) = 1.41421356237309505
sqrt(1^2 + 2^2) = 2.2360679774997897
sqrt(1^2 + 3^2) = 3.16227766016837933
sqrt(1^2 + 4^2) = 4.12310562561766055
sqrt(1^2 + 5^2) = 5.09901951359278483
sqrt(1^2 + 6^2) = 6.08276253029821969
sqrt(1^2 + 7^2) = 7.07106781186547524
sqrt(1^2 + 8^2) = 8.06225774829854965
sqrt(1^2 + 9^2) = 9.05538513813741663
sqrt(1^2 + 10^2) = 10.0498756211208903
0 голосов
/ 05 декабря 2009

код

echo $[(($i * $i) + ($j * $j)) ** $X]

будет работать, если $X является целым числом. Вы пытаетесь получить квадратный корень, и я не уверен, что встроенная арифметика bash сделает это. Для этого вам, вероятно, будет лучше использовать более мощный калькулятор (например, bc и др.).

0 голосов
/ 05 декабря 2009

Обычно вы используете $ ((1 * 3)), но ваш случай не будет работать, поскольку bash не поддерживает числа с плавающей запятой. Вам придется использовать внешний инструмент, такой как awk, bc или dc: http://mywiki.wooledge.org/BashFAQ/022

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...