2009-12-08 2 views
1

В той же ветке, как this question, я даю вам еще один выстрел и спрошу, чтобы помочь решить, как я должен позаботиться об этой проблеме. Я пишу Баш скрипт, который необходимо выполнить следующие действия:Более простая математическая помощь в bash!

  1. У меня есть круг в x и y с радиусом r.
  2. Я указываю resolution, который является расстоянием между точками, которые я проверяю.
  3. Мне нужно зациклиться на x и y (от -r до r) и проверить, находится ли текущий (x, y) в круге, но я перебираю дискретные i и j.
  4. Затем i и j необходимо перейти с -r/resolution на +r/resolution.
  5. В цикле, что должно произойти, это echo "some_text i*resolution j*resolution 15.95 cm" (примечание отсутствует $, потому что я невежественен). Этот вывод - это то, что я действительно ищу.

Мой лучший снимок до сих пор:

r=40.5 
resolution=2.5 
end=$(echo "scale=0;$r/$resolution") | bc 

for ((i=-end; i<=end; i++));do 
    for ((j=-end; j<=end; j++));do 
     x=$(echo "scale=5;$i*$resolution") | bc 
     y=$(echo "scale=5;$j*$resolution") | bc 
     if ((x*x + y*y <= r*r));then  <-- No, r*r will not work 
      echo "some_text i*resolution j*resolution 15.95 cm" 
     fi 
    done 
done 

У меня было почти достаточно с Баш и может выглядеть в KSH, как был предложено кем-то в моем последнем вопросе, но если кто-нибудь знают правильный путь для выполнения этого, пожалуйста, дайте мне знать! Каким бы ни было решение этого, он наверняка установит мой будущий темперамент в стиле bash.

+0

Благодарим за любую помощь; Я вернусь утром несколько часов, чтобы обновить и ответить. – physicsmichael

+1

ksh? пожалуйста...это происходит от плохого к худшему. Мое мнение таково, что вы используете неправильный инструмент. предполагается, что оболочка будет использоваться для запуска программ, а не для математики. –

+0

У меня были проекты, которые настаивали на том, что все должно было быть сделано в оболочке раньше, потому что «никто не знал perl». Иногда вам просто нужно заставить его работать с ограничениями, которые вам даны. Даже если эти ограничения не являются разумными. –

ответ

1

Возможно, вы захотите включить трубу в bc в $(). Вместо.

end=$(echo "scale=0;$r/$resolution") | bc 

использование

end=$(echo "scale=0;$r/$resolution" | bc) 

должно помочь немного.

EDIT И вот решение.

r=40.5 
resolution=2.5 
end=$(echo "scale=0;$r/$resolution" | bc) 

for i in $(seq -${end} ${end}); do 
    for j in $(seq -${end} ${end}); do 
     x=$(echo "scale=5;$i*$resolution" | bc) 
     y=$(echo "scale=5;$j*$resolution" | bc) 

     check=$(echo "($x^2+$y^2)<=$r^2" | bc)  
     if [ ${check} -eq '1' ]; then 
      iRes=$(echo "$i*$resolution" | bc) 
      jRes=$(echo "$j*$resolution" | bc)  
      echo "some_text $iRes $jRes 15.95 cm" 
     fi 
    done 
done 
+0

Адам, последнее эхо печатает только буквально «some_text i * разрешение j * разрешение 15,95 см "! – physicsmichael

+0

Коррекция добавлена, хотя вы можете изменить шкалу для уравнений iRes/jRes в зависимости от ваших требований. –

+0

Спасибо. На моем Mac использование seq должно было быть заменено на x = -end; x physicsmichael

0

Вы еще не слышали о (g) awk ??. то вам следует поучиться об этом. Это принесет вам пользу в долгосрочной перспективе. Перевод вашего скрипта bash на awk.

awk 'BEGIN{ 
    r=40.5 
    resol=2.5 
    end = r/resol 
    print end 
    for (i=-end;i<=end;i++) { 
     for(j=-end;j<=end;j++){ 
      x=sprintf("%.5d",i*resol) 
      y=sprintf("%.5d",j*resol) 
      if (x*x + y*y <= r*r ){ 
       print ".......blah blah ......" 
      } 
     }  
    } 
}' 
0

Он больше похож на bc сценарий, чем Баш один любой путь, так что здесь идет:

#!/usr/bin/bc -q 
/* -q suppresses a welcome banner - GNU extension? */ 
r = 40.5 
resolution = 2.5 

scale = 0 
end = r/resolution 

scale = 5 

for (i = -end; i <= end; i++) { 
    /* moved x outside the j loop since it only changes with i */ 
    x = i * resolution 
    for (j = -end; j <= end; j++) { 
     y = j * resolution 
     if (x^2 * y^2 <= r^2) { 
      /* 
       the next few lines output on separate lines, the quote on 
       a line by itself causes a newline to be created in the output 
       numeric output includes newlines automatically 
       you can comment this out and uncomment the print statement 
       to use it which is a GNU extension 
      */ 
      /* */ 
      "some_text 
" 
      i * resolution 
      j * resolution 
      "15.95 cm 
" 
      /* */ 
      /* non-POSIX: 
      print "some_text ", i * resolution, " ", j * resolution, " 15.95 cm\n" 
      */ 
     } 
    } 
} 
quit 
1

Как уже говорилось эта проблема, вероятно, лучше всего решается с помощью нашей эры, AWK, Ksh или другой был язык.

Pure Bash. Простые задачи, которые на самом деле нуждаются в арифметике с плавающей запятой, иногда могут быть перенесены на какую-то арифметику с фиксированной точкой, используя только целые числа. Следующее решение имитирует 2 десятичных разряда после десятичной точки. Нет необходимости в трубах и внешних процессах внутри петель, если эта точность является достаточной.

factor=100          # 2 digits after the decimal point 
r=4050           # the representation of 40.50 
resolution=250         # the representation of 2.50 
end=$(((r/resolution)*factor))    # correct the result of the division 

for ((i=-end; i<=end; i+=factor)); do 
    for ((j=-end; j<=end; j+=factor)); do 
     x=$(((i*resolution)/factor))   # correct the result of the division 
     y=$(((j*resolution)/factor))   # correct the result of the division 
     if [ $((x*x + y*y)) -le $((r*r)) ] ;then  # no correction needed 
         echo "$x $y ... " 
     fi 
    done 
done 

echo -e "resolution = $((resolution/factor)).$((resolution%factor))" 
echo -e "r   = $((r/factor)).$((r%factor))" 
+0

Сценарий, который я пишу, зависит от определенных пользователем единиц, поэтому я полагаю, что это действительно может работать очень хорошо, если я укажу нанометры! – physicsmichael

Смежные вопросы