Shell skript kompatibilní s POSIX je vyžadován pouze pro podporu integer aritmetika pomocí jazyka shellu ("je vyžadována pouze aritmetika dlouhého celého čísla se znaménkem"), takže čistý shell řešení musí emulovat aritmetika s plovoucí desetinnou čárkou:
item=30
total=70
percent=$(( 100 * item / total + (1000 * item / total % 10 >= 5 ? 1 : 0) ))
100 * item / total
získá zkrácené výsledek celého čísla dělení v procentech.1000 * item / total % 10 >= 5 ? 1 : 0
vypočítá 1. desetinné místo, a pokud je rovno nebo větší než 5, přidá k výsledku celého čísla 1, aby se zaokrouhlilo nahoru.- Všimněte si, že ne je třeba před odkazy na proměnné přidat
$
uvnitř aritmetické expanze$((...))
.
Pokud - v rozporu s premisou otázky - použití externích nástrojů je přijatelné:
awk
nabízí jednoduché řešení, které však přichází s varováním že používá skutečnou binárku s dvojitou přesností hodnoty s plovoucí desetinnou čárkou, a proto mohou přinést neočekávané výsledky v desítkové soustavě reprezentace – např. zkusteprintf '%.0f\n' 28.5
, což dává28
spíše než očekávaných29
):
awk -v item=30 -v total=70 'BEGIN { printf "%.0f\n", 100 * item / total }'
- Všimněte si, jak
-v
se používá k definování proměnných proawk
skript, který umožňuje čisté oddělení mezi jednou citací a tedy doslovaawk
skript a všechny hodnoty předané z shell .
- Naopak, i když
bc
je nástroj POSIX (a proto lze očekávat, že bude přítomen na většině platforem podobných Unixu) a provádí libovolnou přesnost aritmetika, vždy se zkrátí výsledky, takže zaokrouhlení musí provést jiný užitečnost;printf
, nicméně i když se v zásadě jedná o nástroj POSIX, není vyžadován pro podporu specifikátorů formátu s plovoucí desetinnou čárkou (jak se používají vawk
výše), takže následující může, ale nemusí fungovat (a nestojí to za problémy, vzhledem k jednoduššímuawk
řešení a vzhledem k tomu, že problémy s přesností kvůli aritmetice s plovoucí desetinnou čárkou jsou zpět na obrázku):
# !! This MAY work on your platform, but is NOT POSIX-compliant:
# `-l` tells `bc` to set the precision to 20 decimal places, `printf '%.0f\n'`
# then performs the rounding to an integer.
item=20 total=70
printf '%.0f\n' "$(bc -l <<EOF
100 * $item / $total
EOF
)"
Použijte AWK (žádné bash-ismy):
item=30
total=70
percent=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }")
echo $percent
43
Vezmeme-li 2 * původní výpočet procent a získáme z toho modulo 2, získáme přírůstek pro zaokrouhlení.
item=30
total=70
percent=$((200*$item/$total % 2 + 100*$item/$total))
echo $percent
43
(testováno s bash, ash, dash a ksh)
Toto je rychlejší implementace než spouštění koprocesu AWK:
$ pa() { for i in `seq 0 1000`; do pc=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }"); done; }
$ time pa
real 0m24.686s
user 0m0.376s
sys 0m22.828s
$ pb() { for i in `seq 0 1000`; do pc=$((200*$item/$total % 2 + 100*$item/$total)); done; }
$ time pb
real 0m0.035s
user 0m0.000s
sys 0m0.012s
Síla signálu Bluetooth LE Linux
Automatizujte mysql_secure_installation pomocí příkazu echo pomocí skriptu shellu