2012-12-11 55 views
6

Chciałbym przekonwertować liczbę, która jest przechowywana w notacji naukowej na dziesiętne zmiennoprzecinkowe, więc mogę następnie wykonać pewne porównania na danych. Odbywa się to w skrypcie bash - tutaj jest mały fragment kodu:Konwersja notacji naukowej na dziesiętną w bash

while read track_id landfall_num gate_id pres_inter 
do 
    if [[ $landfall_num == 0001 ]] 
    then 
    start_flag = true 
    echo DING DING $start_flag 
    if [[ $pres_inter < 97000 ]] 
    then 
     echo Strong Storm From North $track_id, $gate_id, $pres_inter 
    fi 
    fi 
done < $file 

Moim problemem jest to, że moja < argument jest wybierając przede wszystkim wartościami ciśnienia, które są przechowywane w notacji naukowej, kiedy używaj <, i żadnego, gdy używam >. Patrzę na pomiary ciśnienia atmosferycznego w paskach, a nie na milibarach.

Oto przykładowe dane wyjściowe:

Strong Storm From North 0039988 0017 1.0074E+05 

Strong Storm From North 0037481 0018 9.9831E+04 

Żadna z tych burz powinno być spełnienie kryteriów wyboru!

+0

Dlaczego po prostu nie użyć jednej liniowej perl? –

Odpowiedz

1

Dla porównań liczb, trzeba użyć:

  • -eq zamiast ==
  • -ne zamiast !=
  • -lt zamiast <
  • -le zamiast <=
  • -gt zamiast >
  • -ge zamiast >=

I rozwiązać pewne problemy składni:

while read track_id landfall_num gate_id pres_inter 
do 
    landfall_num=$(printf "%f", "$landfall_num") 
    if [[ "$landfall_num" -eq 1 ]] 
    then 
    start_flag="true" 
    echo "DING DING $start_flag" 
    if [[ "$pres_inter" -lt 97000 ]] 
    then 
     echo "Strong Storm From North $track_id, $gate_id, $pres_inter" 
    fi 
    fi 
done < "$file" 

Aktualizacja:

ten sposób można przekonwertować naukowej liczby notacji do liczby całkowitej:

printf "%.0f\n", 1.0062E+05 

na przykład druki:

100620 

I tak:

landfall_num=$(printf "%f", "$landfall_num") 

będzie konwertować landfall_num z notacji naukowej do normalnego liczba dziesiętna.

+0

dziękuję. Po prostu ciekawy - w zeszłym tygodniu wziąłem kurs programowania powłoki i nie rozmawiali o wszystkich cudzysłowach. Dlaczego uważasz tę lepszą składnię? Dzięki! – kimmyjo221

+0

Ponadto pojawia się następujący błąd: wiersz 28: [[: 1.0062E + 05: błąd składni: niepoprawny operator arytmetyczny (znacznik błędu to ".0062E + 05") – kimmyjo221

+0

Niemal zawsze lepiej jest zamieścić zmienne w podwójnych cudzysłowach eliminuj przypadki narożne, takie jak puste ciągi lub ciągi zawierające znaki nowej linii. –

6

Po pierwsze, bash nie może wykonywać arytmetyki za pomocą Arytmetyki zmiennoprzecinkowej. Po drugie, bash nie zna notacji naukowej (nawet dla liczb całkowitych).

Pierwszą rzeczą, można spróbować, jeśli jesteś absolutnie pozytywnie się, że wszystkie liczby są liczbami całkowitymi: przekształcają je w notacji dziesiętnej: printf chętnie zrobić dla Ciebie:

printf -v pres_inter "%.f" "$pres_inter" 

(%.f rundy do najbliższego liczba całkowita).

następnie użyć bash za arytmetyki:

if ((pres_inter < 97000)); then .... 

Rozwiązanie to jest wspaniałe i nie używa żadnych zewnętrznych poleceń ani żadnych podpowłok: szybkość i skuteczność!

Teraz, jeśli masz do czynienia z nie liczb lepiej wykorzystywać bc zrobić arytmetyki: ale ponieważ bc jest opóźniony i nie ma dobrze radzić sobie z notacji naukowej, trzeba konwertować swoje numery do notacji dziesiętnej jakikolwiek . Więc coś w następujących powinien zrobić:

printf -v pres_inter "%f" "$pres_inter" 
if (($(bc -l <<< "$pres_inter<97000"))); then ... 

Oczywiście, jest to wolniejszy ponieważ jesteś rozwidlone się bc. Jeśli jesteś szczęśliwy z liczbami całkowitymi, po prostu trzymaj się pierwszej możliwości, którą dałem.

Gotowe!