Szybki przykład tego, czego chcę za pomocą skryptów bash:
#!/bin/bash
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
echo "scale=2; $float/1.18" |bc -l
read -p "Press any key to continue..."
bash scriptname.sh
Zakładając, że cena wynosi: 48,86 Odpowiedź brzmi: 41.406779661 (41,40 właściwie ponieważ używam scale=2;
)
Moje pytanie brzmi: jak zaokrąglić drugi przecinek, aby pokazać odpowiedź w ten sposób ?: 41,41
bc
nie jest w stanie osiągnąć tego, o co się prosi (a przynajmniej pytania, które zadałem, kiedy znalazłem ten post), czyli jak zaokrąglać ułamki dziesiętne za pomocąbc
(to się nazywabash
).r()
funkcją, dzięki czemu można jej używaćbc -le "r($float/1.18, 2)"
.Odpowiedzi:
Funkcja bash round:
Używane w twoim przykładzie kodu:
Powodzenia: o)
źródło
-0.5
$2 = 3
Musiałem użyćecho $(env printf %.3f $(echo "scale=3;((1000*$1)+0.5)/1000" | bc))
. Pamiętaj o env przed printf! To nauczy Cię ponownie, że zawsze ważne jest, aby zrozumieć, co kopiujesz z innego miejsca.if [
echo „$ 1/1” | bc` -gt 0] `- czy istnieje bardziej elegancki sposób sprawdzania (oprócz parsowania ciągu dla„ - ”)?Najprostsze rozwiązanie:
źródło
+0.5
. Spróbuj,printf "%.2f\n" "$(bc -l <<<"48.86/1.18")" "$(bc -l <<<"-48.86/1.18")"
a dostaniesz41.41
i-41.41
.echo "$float/1.18" | bc -l | xargs printf %.2f
bash: printf: 1.69491525423728813559: invalid number
w zależności od ustawień regionalnych.Zaokrąglanie Bash / awk:
Jeśli masz python, możesz użyć czegoś takiego:
źródło
echo "$float" |awk '{printf "%.2f", $1/1.18}'
wykona zadaną matematykę pytania z żądaną dokładnością setnych części. To tyle samo „używania bash”, cobc
wywołanie w pytaniu.python -c "print(round($num))"
gdzienum=4.678923
. Nie ma potrzeby, aby grzebać w standardzie. Można również okrągły do n cyfr tak:python -c "print(round($num, $n))"
.echo 5 | python -c "print int(round((float(raw_input())/2)-0.5))"
(Kiedy + zaokrągli w górę i - zaokrągli w dół).Oto rozwiązanie wyłącznie BC. Zasady zaokrąglania: przy +/- 0,5, zaokrąglić od zera.
Umieść skalę, której szukasz, w $ result_scale; matematyka powinna znajdować się w miejscu, w którym $ MATH znajduje się na liście poleceń bc:
źródło
MATH=-0.34;result_scale=1;bc <<MATH
, #ObjectiveAndClear: 5 jak wyjaśniono tutaj :)Wiem, że to stare pytanie, ale mam czyste rozwiązanie „bc” bez „if” lub rozgałęzień:
Użyj go jak
bcr '2/3' 5
lubbcr '0.666666' 2
-> (wyrażenie poprzedzone skalą)Jest to możliwe, ponieważ w bc (jak C / C ++) dozwolone jest mieszanie wyrażeń logicznych w twoich obliczeniach. Wyrażenie
((t>0)-(t<0))/2)
będzie miało wartość +/- 0,5 w zależności od znaku „t”, a zatem zastosuje odpowiednią wartość do zaokrąglenia.źródło
bcr "5 / 2" 0
zwraca2
zamiast3
. Czy coś brakuje?To jest naprawdę proste: nie ma potrzeby jawnego dodawania zakodowanego wariantu „-0,5” dla liczb ujemnych. Mówiąc matematycznie, po prostu obliczymy wartość bezwzględną argumentu i nadal dodamy 0,5, jak zwykle. Ale ponieważ (niestety) nie mamy do dyspozycji żadnej wbudowanej
abs()
funkcji (chyba że ją kodujemy), po prostu zanegujemy argument, jeśli jest on ujemny.Poza tym praca z ilorazem jako parametrem okazała się bardzo kłopotliwa (ponieważ dla mojego rozwiązania muszę mieć dostęp do dywidendy i dzielnika osobno). Dlatego mój skrypt ma dodatkowy trzeci parametr.
źródło
echo .. |
, arytmetyki powłoki, jaki jest sensecho $()
? Łatwo to wytłumaczyć: ciągi tutaj będą zawsze wymagały zapisu/tmp
katalogu! I moje rozwiązanie będzie również pracować w środowisku tylko do odczytu, np rootem awaryjnego gdzie/
jest nie zawsze zapisu domyślnie. Był więc dobry powód, dla którego kodowałem to w ten sposób.echo $()
kiedykolwiek potrzebne? To i wcięcie skłoniło mnie do edycji, właśnie tu się pojawiły.echo $()
który został naprawiony, była przedostatnia linia, lol. Dzięki za zgłoszenie się. Przynajmniej ten wygląda teraz znacznie lepiej, nie mogę zaprzeczyć. W każdym razie podobała mi się logika. Dużo boolowskich rzeczy, mniej zbędnych „jeśli” (co z pewnością wysadziłoby kod o 50 procent).Wciąż szukam czystej
bc
odpowiedzi na to, jak zaokrąglić tylko jedną wartość w funkcji, ale oto czystabash
odpowiedź:Zasadniczo, to ostrożnie wyodrębnia ułamki dziesiętne, mnoży wszystko przez 100 miliardów (10¹⁰,
10**10
inbash
), dostosowuje precyzję i zaokrąglanie, dokonuje rzeczywistego podziału, dzieli z powrotem do odpowiedniej wielkości, a następnie ponownie wprowadza ułamek dziesiętny.Krok po kroku:
W
embiggen()
wyznacza funkcyjne ściętego całkowitą postaci jej argumentu$int
i zapisuje numery po kropką$fraction
. Liczba cyfr ułamkowych jest zapisana w$precision
. Mnoży matematyczne 10¹⁰ przez złączenie$int
i$fraction
, a następnie dostosowuje się, że w celu dopasowania do precyzji (npembiggen 48.86
się 10¹⁰ x 4886/100 i wraca488600000000
który jest 488600000000).Chcemy ostatecznej precyzji setnych, więc mnożymy pierwszą liczbę przez 100, dodajemy 5 dla celów zaokrąglania, a następnie dzielimy drugą liczbę. To zadanie
$answer
pozostawia nas sto razy ostateczną odpowiedź.Teraz musimy dodać przecinek dziesiętny. Przypisujemy nową
$int
wartość$answer
wykluczeniu ostatnich dwóch cyfr, następnieecho
kropką i$answer
wykluczeniu$int
wartości, o którą już zadbano. (Nie wspominając o błędzie podświetlania składni, który sprawia, że wygląda to jak komentarz)(Bashism: potęgowanie nie jest POSIX, więc jest to bashism. Czyste rozwiązanie POSIX wymagałoby, aby pętle dodawały zera, a nie używały potęg dziesięciu. Ponadto „embiggen” to słowo doskonale cromulant.)
Jednym z głównych powodów, dla których używam
zsh
mojej powłoki jest to, że obsługuje matematykę zmiennoprzecinkową. Rozwiązanie tego pytania jest dość proste wzsh
:(Chciałbym zobaczyć, jak ktoś dodaje komentarz do tej odpowiedzi, podając sztuczkę włączenia arytmetyki zmiennoprzecinkowej
bash
, ale jestem pewien, że taka funkcja jeszcze nie istnieje.)źródło
jeśli masz wynik, na przykład rozważ 2.3747888
wszystko co musisz zrobić to:
to poprawnie zaokrągla liczbę, przykład:
ułamki dziesiętne są usuwane przez,
bc
więc zaokrągla w dół do 2, tak jak powinnoźródło
Musiałem obliczyć całkowity czas trwania zbioru plików audio.
Musiałem więc:
A. uzyskaj czas trwania każdego pliku ( nie pokazano )
B. zsumuj wszystkie czasy trwania (wszystkie były w
NNN.NNNNNN
(fp) sekundach)C. oddzielne godziny, minuty, sekundy, sekundy.
D. wyprowadzić ciąg HR: MIN: SEK: ZDJĘCIA, gdzie ramka = 1/75 sek.
(Ramki pochodzą z kodu SMPTE używanego w studiach).
Odp .: użyj
ffprobe
i parsuj czas trwania linii na numer fp (nie pokazano)B:
DO:
RE:
źródło
Oto skrócona wersja skryptu, naprawiona w celu zapewnienia pożądanych wyników:
Zauważ, że zaokrąglenie w górę do najbliższej liczby całkowitej jest równoważne dodaniu .5 i zabraniu głosu lub zaokrągleniu w dół (dla liczb dodatnich).
Ponadto współczynnik skali jest stosowany w momencie operacji; więc (są to
bc
polecenia, możesz je wkleić do terminala):źródło
Implementacja czystego bc zgodnie z żądaniem
define ceil(x) { auto os,xx;x=-x;os=scale;scale=0 xx=x/1;if(xx>x).=xx-- scale=os;return(-xx) }
jeśli umieścisz to w pliku o nazwie functions.bc, możesz zaokrąglić w górę za pomocą
echo 'ceil(3.1415)' | bc functions.bc
Kod implementacji bc można znaleźć na stronie http://phodd.net/gnu-bc/code/funcs.bc
źródło
źródło
Możesz użyć awk, bez rur:
Ustaw wcześniej cenę za pomocą zmiennej środowiskowej
PRICE=<val>
.Następnie wywołaj awk -
$PRICE
przejdzie do awk jako zmienna awkprice
.Następnie jest zaokrąglany w górę do najbliższej setnej z +.005.
Opcja formatowania printf
%.2f
ogranicza skalę do dwóch miejsc po przecinku.Jeśli musisz to robić dużo w ten sposób, jest to o wiele bardziej wydajne niż wybrana odpowiedź:
źródło