2009-12-08 6 views
1

Dans le même fil que this question, je donne un autre coup de feu et demander SO pour aider à résoudre la façon dont je devrais régler ce problème. J'écris un script bash qui doit effectuer les opérations suivantes:Une aide mathématique plus simple à bash!

  1. J'ai un cercle x et y avec un rayon r.
  2. Je spécifie resolution qui est la distance entre les points que je vérifie.
  3. J'ai besoin de boucle sur x et y (de -r à r) et de vérifier si le courant (x, y) est dans le cercle, mais je boucle sur discrète i et j à la place.
  4. Puis i et j doivent passer de -r/resolution à +r/resolution.
  5. Dans la boucle, ce qui doit se produire est echo "some_text i*resolution j*resolution 15.95 cm" (noter l'absence de $ parce que je suis clueless). Cette sortie est ce que je cherche vraiment.

Mon meilleur coup jusqu'à présent:

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 

J'ai eu juste assez avec bash et peut regarder dans ksh comme cela a été suggéré par quelqu'un dans ma dernière question, mais si quelqu'un connait une bonne façon pour l'exécuter, s'il vous plaît faites le moi savoir! Quelle que soit la solution à ce problème, mon tempérament futur sera sûrement orienté vers le script bash.

+0

Merci pour toute aide; Je serai de retour dans la matinée quelques heures pour mettre à jour et répondre. – physicsmichael

+1

ksh? S'il vous plaît...ça va de mal en pis. Mon opinion est que vous utilisez le mauvais outil. un shell est censé être utilisé pour exécuter des programmes, pas pour faire des maths. –

+0

J'ai eu des pistes de projet insistent sur le fait que tout devait être fait dans le shell avant, parce que 'personne ne savait perl'. Parfois, vous devez le faire fonctionner avec les contraintes qui vous ont été données. Même si ces contraintes ne sont pas saines. –

Répondre

1

Vous pouvez inclure le tuyau dans bc dans $(). Au lieu de.

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

utilisation

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

devrait aider un peu.

EDIT Et voici une solution.

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

Adam, l'écho final imprime rien mais littéralement "some_text je * résolution j * résolution 15,95 cm "! – physicsmichael

+0

Correction ajoutée, bien que vous souhaitiez changer l'échelle pour les équations iRes/jRes en fonction de vos besoins. –

+0

Merci. Sur mon Mac, l'utilisation de seq devait être remplacée par x = -end; x physicsmichael

0

vous n'avez pas entendu parler de (g) awk ??. alors vous devriez aller apprendre à ce sujet. Cela vous profitera à long terme. Traduction de votre script bash pour 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

Il cherche plus comme un script bc qu'un Bash une quelconque manière, il faut en tenir:

#!/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

Comme déjà mentionné ce problème est probablement mieux résolu en utilisant bc, awk, ksh ou un autre script la langue.

Bash pure. Les problèmes simples qui nécessitent réellement l'arithmétique à virgule flottante peuvent parfois être transposés à une sorte d'arithmétique à virgule fixe en utilisant uniquement des entiers. La solution suivante simule 2 décimales après le point décimal. Il n'y a pas besoin de tuyaux et de processus externes à l'intérieur des boucles si cette précision est suffisante.

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

Le script que j'écris actuellement repose sur des unités spécifiées par l'utilisateur, donc je suppose que cela pourrait très bien marcher si je spécifie des nanomètres! – physicsmichael