Próbuję podzielić dwie szerokości obrazu w skrypcie Bash, ale bash daje mi 0
w rezultacie:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
Przestudiowałem przewodnik po Bash i wiem, że powinienem go użyć bc
we wszystkich przykładach w Internecie, których używają bc
. W echo
starałem się umieścić tę samą rzecz w moim SCALE
, ale to nie działa.
Oto przykład, który znalazłem w tutorialach:
echo "scale=2; ${userinput}" | bc
Jak mogę sprawić, żeby Bash dał mi pływaka 0.5
?
bash
floating-point
arithmetic-expressions
Medya Gh
źródło
źródło
Odpowiedzi:
Nie możesz bash robi tylko liczby całkowite; Państwo musi przekazać narzędzia takiego jak
bc
.źródło
VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)
lubVAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")
bez $ (()) (podwójne nawiasy); który jest rozszerzany przez bash przed wykonaniem poleceniamożesz to zrobić:
AKTUALIZACJA
20130926
: możesz użyć:źródło
bc -l <<< 'scale=2; 100/3'
Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.
I jest dodatkowa uwaga dla/
operatora:The scale of the result is the value of the variable scale.
bc <<< 'scale=1; 1*3.00001'
skala jest naprawdę 5 z jakiegoś powodu,bc <<< 'scale=1; 1/3.000001'
skala wynosi 1. Co ciekawe, dzielenie przez 1 ustawia to prosto:bc <<< 'scale=1; 1*3.00001/1'
skala to 1grzmotnąć
Jak zauważyli inni,
bash
nie obsługuje arytmetyki zmiennoprzecinkowej, chociaż można ją sfałszować za pomocą pewnych stałych sztuczek dziesiętnych, np. Z dwoma miejscami po przecinku:Wynik:
Zobacz odpowiedź Nilfreda na podobne, ale bardziej zwięzłe podejście.
Alternatywy
Oprócz wspomnianych
bc
iawk
alternatywnych istnieją również:clisp
z oczyszczoną mocą wyjściową:
lub poprzez stdin:
dc
genialny kalkulator cli
ghostscript
gnuplot
jq
Lub:
ksh
lua
lub poprzez stdin:
maksima
z oczyszczoną mocą wyjściową:
węzeł
oktawa
perl
python2
python3
R
z oczyszczoną mocą wyjściową:
rubin
wcalc
Z oczyszczoną mocą wyjściową:
zsh
jednostki
Z kompaktową mocą wyjściową:
Innych źródeł
Stéphane Chazelas odpowiedział na podobne pytanie w Unix.SX.
źródło
echo 1/3 | node -p
jest krótki.Poprawiając nieco odpowiedź marvina:
bc nie zawsze jest dostarczany jako zainstalowany pakiet.
źródło
exit
uniemożliwić odczyt ze strumienia wejściowego. Sugeruję również użycie-v
flag awk, aby zapobiec zespołowi pochylonej wykałaczki. Więc:RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "
.bc
jest częścią POSIX, zwykle jest wstępnie zainstalowany.Możesz użyć bc według
-l
opcji (litera L)źródło
-l
w moim systemie, bc nie wykona matematyki zmiennoprzecinkowej.Jako alternatywę dla bc możesz użyć awk w swoim skrypcie.
Na przykład:
Powyżej „% .2f” mówi funkcji printf, aby zwracała liczbę zmiennoprzecinkową z dwiema cyframi po miejscu dziesiętnym. Użyłem echa do potokowania zmiennych jako pól, ponieważ awk działa na nich poprawnie. „$ 1” i „$ 2” odnoszą się do pierwszego i drugiego pola wprowadzonego do awk.
Możesz zapisać wynik jako inną zmienną, używając:
źródło
To idealny czas, aby wypróbować Zsh, (prawie) superset Bash, z wieloma dodatkowymi funkcjami, w tym matematyką zmiennoprzecinkową. Oto twój przykład w Zsh:
Ten post może ci pomóc: bash - Warto przejść na zsh do codziennego użytku?
źródło
Cóż, zanim liczba zmiennoprzecinkowa była okresem, w którym stosowano stałą logikę dziesiętną:
Ostatnia linia to bashim, jeśli nie używasz bash, wypróbuj ten kod:
Uzasadnieniem tego kodu jest: pomnóż przez 100 przed dzieleniem, aby uzyskać 2 miejsca po przecinku.
źródło
Jeśli znalazłeś wariant preferencji, możesz również zawinąć go w funkcję.
Tutaj zawijam trochę bashizmu w funkcję div:
Jedna wkładka:
Lub wiele linii:
Teraz masz funkcję
i używaj go jak
AKTUALIZACJA Dodałem mały skrypt, który zapewnia podstawowe operacje z liczbami zmiennoprzecinkowymi dla bash:
Stosowanie:
A tutaj skrypt:
źródło
local _d=${3:-2}
jest prostszeTo naprawdę nie jest zmiennoprzecinkowe, ale jeśli chcesz czegoś, co ustawia więcej niż jeden wynik w jednym wywołaniu bc ...
oblicza powierzchnię i średnicę koła, którego promień podano w 1 $
źródło
Istnieją scenariusze, w których nie można używać bc, ponieważ może po prostu nie być obecny, jak w niektórych odciętych wersjach busyboksa lub systemach wbudowanych. W każdym razie dobrze jest ograniczyć zewnętrzne zależności, dlatego zawsze możesz dodawać zera do liczby dzielonej przez (licznik), to znaczy tyle samo, co mnożenie przez potęgę 10 (powinieneś wybrać potęgę 10 zgodnie z potrzebna precyzja), dzięki czemu wynik dzielenia będzie liczbą całkowitą. Gdy masz już tę liczbę całkowitą, potraktuj ją jako ciąg znaków i ustaw kropkę dziesiętną (przesuwając ją od prawej do lewej) kilka razy równą potędze dziesięciu, pomnożąc licznik. Jest to prosty sposób uzyskiwania wyników zmiennoprzecinkowych przy użyciu tylko liczb całkowitych.
źródło
Chociaż nie można używać podziału zmiennoprzecinkowego w Bash, można zastosować podział stały. Wszystko, co musisz zrobić, to pomnożyć liczby całkowite przez potęgę 10, a następnie oddzielić część całkowitą i użyć operacji modulo, aby uzyskać część ułamkową. Zaokrąglanie w razie potrzeby.
źródło
wiem, że jest stary, ale zbyt kuszący. więc odpowiedź brzmi: nie możesz ... ale możesz. Spróbujmy tego:
w ten sposób dostajesz 2 cyfry po punkcie, obcięte (nazwij to zaokrąglaniem do niższej, haha) w czystym bashu (nie musisz uruchamiać innych procesów). oczywiście, jeśli potrzebna jest tylko jedna cyfra po punkcie, mnożymy przez 10 i robimy modulo 10.
co to robi:
bonusowy utwór : wersja bc x 1000 zajęła 1,8 sekundy na moim laptopie, podczas gdy czysty bash zajął 0,016 sekundy.
źródło
Jak wykonać obliczenia zmiennoprzecinkowe w bash:
Zamiast używać „ tutaj ciągów ” (
<<<
) zbc
poleceniem, tak jak robi to jeden z najbardziej popularnych przykładów , oto mój ulubionybc
przykład zmiennoprzecinkowy, bezpośrednio zEXAMPLES
sekcjibc
stron podręcznika man (zobaczman bc
podręcznika strony podręcznika).Zanim zaczniemy, wiedzą, że równanie dla PI:
pi = 4*atan(1)
.a()
poniżej znajduje siębc
funkcja matematyczna dlaatan()
.W ten sposób zapisujesz wynik obliczeń zmiennoprzecinkowych w zmiennej bash - w tym przypadku w zmiennej o nazwie
pi
. Zauważ, żescale=10
w tym przypadku ustawia liczbę cyfr dziesiętnych dokładności na 10. Wszelkie cyfry dziesiętne po tym miejscu są obcinane .Teraz, aby mieć jeden wiersz kodu, który również wypisuje wartość tej zmiennej, po prostu dodaj
echo
polecenie na końcu jako polecenie uzupełniające, w następujący sposób. Zwróć uwagę na obcięcie z 10 miejscami po przecinku, zgodnie z rozkazem:Na koniec wrzućmy zaokrąglenie. Tutaj użyjemy
printf
funkcji do zaokrąglenia do 4 miejsc po przecinku. Zauważ, że3.14159...
rundy teraz do3.1416
. Ponieważ zaokrąglamy, nie musimy już używaćscale=10
przycinania do 10 miejsc po przecinku, więc po prostu usuniemy tę część. Oto końcowe rozwiązanie:Oto kolejna naprawdę świetna aplikacja i prezentacja powyższych technik: pomiar i drukowanie czasu wykonywania.
Uwaga:
dt_min
zaokrągla się0.01666666666...
do0.017
:Związane z:
źródło
Użyj obliczeń To najłatwiejszy przykład jaki znalazłem:
źródło
Dla tych, którzy próbują obliczyć procenty z zaakceptowaną odpowiedzią, ale tracą precyzję:
Jeśli uruchomisz to:
Dostajesz
99.00
tylko to, co traci precyzję.Jeśli uruchomisz to w ten sposób:
Teraz masz
99.99
.Ponieważ skalujesz tylko w momencie drukowania.
Zobacz tutaj
źródło
** Bezpieczna wtryskowa matematyka zmiennoprzecinkowa w bash / shell **
Uwaga: Celem tej odpowiedzi jest dostarczenie pomysłów na bezpieczne dla iniekcji rozwiązanie wykonywania matematyki w bash (lub innych powłokach). Oczywiście to samo można zastosować, z niewielkim dostosowaniem w celu przeprowadzenia zaawansowanego przetwarzania łańcucha itp.
Większość przedstawionych rozwiązań polega na tworzeniu małych skryptletów w locie przy użyciu danych zewnętrznych (zmiennych, plików, wiersza poleceń, zmiennych środowiskowych). Zewnętrzne dane wejściowe można wykorzystać do wstrzyknięcia złośliwego kodu do silnika, wielu z nich
Poniżej znajduje się porównanie używania różnych języków do wykonywania podstawowych obliczeń matematycznych, których wynikiem jest liczba zmiennoprzecinkowa. Oblicza A + B * 0,1 (jako zmiennoprzecinkowy).
Wszystkie próby rozwiązania unikają tworzenia skryptletów dynamicznych, które są niezwykle trudne w utrzymaniu, zamiast tego używają programu statycznego i przekazują parametry do wyznaczonej zmiennej. Będą bezpiecznie obsługiwać parametry ze znakami specjalnymi - zmniejszając możliwość wstrzyknięcia kodu. Wyjątkiem jest „BC”, który nie zapewnia funkcji wejścia / wyjścia
Wyjątkiem jest „bc”, który nie zapewnia żadnych danych wejściowych / wyjściowych, wszystkie dane są przesyłane przez programy w stdin, a wszystkie dane wyjściowe są przesyłane do stdout. Wszystkie obliczenia są wykonywane w piaskownicy, co nie pozwala na efekt uboczny (otwieranie plików itp.). Teoretycznie wtrysk bezpieczny z założenia!
źródło
python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"
„4200.0” ==> 4205.63oto polecenie awk: -F = separator pól == +
źródło