Chcę zrobić pętlę for w bashu z 0,02 jako przyrosty, których próbowałem
for ((i=4.00;i<5.42;i+=0.02))
do
commands
done
ale to nie zadziałało.
bash
for
floating-point
Mehrshad
źródło
źródło
bc
, ale zatrzymanie na 4.52 może być trudne. skorzystaj z sugestii @roaima, zastosuj pomocniczy var z krokiem 2, i użyji=$(echo $tmp_var / 100 | bc)
Odpowiedzi:
Czytanie
bash
strony podręcznika daje następujące informacje:a następnie otrzymujemy tę sekcję
Widać więc wyraźnie, że nie można użyć
for
pętli z wartościami innymi niż całkowite.Jednym z rozwiązań może być po prostu pomnożenie wszystkich składników pętli przez 100, pozwalając na to, gdzie będziesz ich później używać, na przykład:
źródło
k=400;k<542;k+=2
ponieważ pozwala uniknąć potencjalnych problemów arytmetycznych zmiennoprzecinkowych.bc
), rozwidlasz proces, tworzysz plik tymczasowy (dla ciągu tutaj), wykonujeszbc
w nim (co oznacza ładowanie bibliotek wykonywalnych i współdzielonych oraz inicjowanie ich), poczekaj na to i posprzątaj. Uruchomieniebc
raz w celu wykonania pętli byłoby znacznie bardziej wydajne.i=$(bc <<< "scale...")
lubi=$(echo "scale..." | bc)
<<<
pochodzi),bash
iksh
. Zauważ, że przejście na inną powłokę niżbash
da lepszy wzrost wydajności niż użycie innej składni.<<<
(zsh, mksh, ksh93, Yash) również wspierać pływających arytmetyki Point (zsh
,ksh93
,yash
)).Unikaj pętli w muszlach.
Jeśli chcesz wykonywać arytmetykę, użyj
awk
lubbc
:Lub
Zauważ, że
awk
(w przeciwieństwie dobc
) współpracuje z procesoramidouble
reprezentacji liczb zmiennoprzecinkowych (prawdopodobnie typu IEEE 754 ). W rezultacie, ponieważ te liczby są binarnymi przybliżeniami tych liczb dziesiętnych, możesz mieć pewne niespodzianki:Jeśli dodasz
OFMT="%.17g"
, możesz zobaczyć przyczynę braku0.3
:bc
wykonuje dowolną precyzję, więc nie ma tego rodzaju problemów.Zauważ, że domyślnie (chyba że zmienisz format wyjściowy za pomocą
OFMT
lub użyjeszprintf
jawnych specyfikacji formatu),awk
używa%.6g
do wyświetlania liczb zmiennoprzecinkowych, więc przełącza się na 1e6 i więcej dla liczb zmiennoprzecinkowych powyżej 1 000 000 i obcina część ułamkową dla wysokich liczb (100000,02 będzie wyświetlany jako 100000).Jeśli naprawdę potrzebujesz użyć pętli powłoki, ponieważ na przykład chcesz uruchomić określone polecenia dla każdej iteracji tej pętli, użyj powłoki z obsługą arytmetyki zmiennoprzecinkowej
zsh
,yash
lub,ksh93
lub wygeneruj listę wartości za pomocą jednego polecenia, jak powyżej (lubseq
jeśli jest dostępny) i zapętlić jego wynik.Lubić:
Lub:
o ile nie przekroczysz limitów liczb zmiennoprzecinkowych procesora, obsługa
seq
błędów wynikających z przybliżeń zmiennoprzecinkowych jest bardziej płynna niż w przypadkuawk
wersji powyżej.Jeśli nie masz
seq
(polecenia GNU), możesz uczynić je bardziej niezawodnym jako funkcja:To działałoby lepiej w przypadku takich rzeczy
seq 100000000001 0.000000001 100000000001.000000005
. Zauważ jednak, że posiadanie liczb z dowolnie wysoką precyzją niewiele pomoże, jeśli przekażemy je poleceniom, które ich nie obsługują.źródło
unset IFS
w pierwszym przykładzie?IFS=$'\n'
ale to nie działa we wszystkich powłokach. Lub,IFS='<a-litteral-newline-here>'
ale to nie jest bardzo czytelne. Lub możemy zamiast tego podzielić na słowa (spacja, tabulator, nowa linia), tak jak w przypadku domyślnej wartości $ IFS lub jeśli odłączysz IFS i również tutaj działa.IFS
, ponieważ wiemy, że naseq
wyjściu nie ma spacji, w których musimy uniknąć podziału. Ma to na celu przede wszystkim upewnienie się, że ten przykład zależy od tegoIFS
, co może mieć znaczenie dla innej komendy generującej listę.Użyj „seq” - wypisz ciąg liczb
kolejny PIERWSZE NARUSZENIE OSTATNIE
źródło
Jak sugerują inni, możesz użyć bc:
źródło