Как использовать деление с плавающей запятой в bash?

Я пытаюсь разделить две ширины изображения в сценарии Bash, но bash дает мне 0 в качестве результата:

 RESULT=$(($IMG_WIDTH/$IMG2_WIDTH)) 

Я изучил руководство Bash, и я знаю, что должен использовать bc , во всех примерах в Интернете они используют bc . В echo я попытался поместить то же самое в свою SCALE но это не сработало.

Вот пример, который я нашел в учебниках:

 echo "scale=2; ${userinput}" | bc 

Как я могу заставить Баша дать мне поплавок, равный 0.5 ?

Вы не можете. bash только целые числа; вы должны делегировать инструмент, такой как bc .

вы можете сделать это:

 bc <<< 'scale=2; 100/3' 33.33 

UPDATE 20130926 : вы можете использовать:

 bc -l <<< '100/3' # saves a few hits 

удар

Как отмечают другие, bash не поддерживает арифметику с плавающей запятой, хотя вы можете подделать ее с некоторым фиксированным десятичным обманом, например, с двумя десятичными знаками:

 echo $(( 100 * 1 / 3 )) | sed 's/..$/.&/' 

Вывод:

 .33 

См . Ответ Нильфреда для аналогичного, но более сжатого подхода.

альтернативы

Помимо упомянутых альтернатив bc и awk существуют также следующие:

CLISP

 clisp -x '(/ 1.0 3)' 

с очищенным выходом:

 clisp --quiet -x '(/ 1.0 3)' 

или через stdin:

 echo '(/ 1.0 3)' | clisp --quiet | tail -n1 

Округ Колумбия

 echo 2k 1 3 /p | dc 

гениальный калькулятор cli

 echo 1/3.0 | genius 

Gnuplot

 echo 'pr 1/3.' | gnuplot 

JQ

 echo 1/3 | jq -nf /dev/stdin 

Или:

 jq -n 1/3 

КШ

 echo 'print $(( 1/3. ))' | ksh 

Lua

 lua -e 'print(1/3)' 

или через stdin:

 echo 'print(1/3)' | lua 

максима

 echo '1/3,numer;' | maxima 

с очищенным выходом:

 echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p' 

узел

 echo 1/3 | node -p 

октава

 echo 1/3 | octave 

Perl

 echo print 1/3. | perl 

питон

 echo print 1/3. | python 

р

 echo 1/3 | R --no-save 

с очищенным выходом:

 echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p' 

Рубин

 echo print 1/3.0 | ruby 

Wcalc

 echo 1/3 | wcalc 

С очищенным выходом:

 echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2 

ЗШ

 echo 'print $(( 1/3. ))' | zsh 

Другие источники

Стефан Чазелас ответил на аналогичный вопрос в Unix.SX.

Несколько улучшив ответ марвина:

 RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}") 

bc не всегда устанавливается как установленный пакет.

Вы можете использовать bc с помощью опции -l (L-буква)

 RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l) 

В качестве альтернативы bc вы можете использовать awk в своем скрипте.

Например:

 echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}' 

В приведенном выше примере «% .2f» сообщает функции printf возвращать число с плавающей запятой с двумя цифрами после десятичной точки. Я использовал эхо-канал для переменных в качестве полей, так как awk корректно работает с ними. «$ 1» и «$ 2» относятся к первому и второму полям, введенным в awk.

И вы можете сохранить результат как какую-то другую переменную, используя:

 RESULT = `echo ...` 

Это идеальное время, чтобы попробовать zsh, (почти) bash superset, со многими дополнительными приятными функциями, включая математику с плавающей запятой. Вот как ваш пример будет выглядеть в zsh:

 % IMG_WIDTH=1080 % IMG2_WIDTH=640 % result=$((IMG_WIDTH*1.0/IMG2_WIDTH)) % echo $result 1.6875 

Это сообщение может вам помочь: bash – стоит переключиться на zsh для случайного использования?

Хорошо, прежде чем плавать было время, когда была использована логика с фиксированными десятичными знаками:

 IMG_WIDTH=100 IMG2_WIDTH=3 RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH)) echo "${RESULT:0:-2}.${RESULT: -2}" 33.33 

Последняя строка – это bashim, если не использовать bash, попробуйте этот код:

 IMG_WIDTH=100 IMG2_WIDTH=3 INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH)) DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH))) RESULT=$INTEGER.$DECIMAL echo $RESULT 33.33 

Обоснование кода: умножить на 100 до деления, чтобы получить 2 десятичных знака.

Существуют сценарии, в которых вы не можете использовать bc, потому что это может просто не присутствовать, например, в некоторых сокращенных версиях busybox или встроенных систем. В любом случае ограничение внешних зависимостей всегда полезно, так что вы всегда можете добавить нули к числу, делящемуся на (числитель), то есть то же самое, что умножить на мощность 10 (вы должны выбрать мощность 10 согласно нужная вам точность), которая заставит деление выводить целое число. Когда у вас есть это целое число, рассматривайте его как строку и поместите десятичную точку (перемещая ее справа налево), количество раз равное мощности десяти, умноженное на числитель. Это простой способ получения результатов float с использованием только целочисленных чисел.

Это не плавающая точка, но если вы хотите что-то, что задает более одного результата в одном вызове bc …

 source /dev/stdin <<<$(bc <<< ' d='$1'*3.1415926535897932384626433832795*2 print "d=",d,"\n" a='$1'*'$1'*3.1415926535897932384626433832795 print "a=",a,"\n" ') echo bc radius:$1 area:$a diameter:$d 

вычисляет площадь и диаметр круга, радиус которого задан в $ 1

Хотя вы не можете использовать деление с плавающей запятой в Bash, вы можете использовать деление с фиксированной точкой. Все, что вам нужно сделать, это умножить целые числа на 10, а затем разделить целочисленную часть и использовать модульную операцию для получения дробной части. Округление по мере необходимости.

 #!/bin/bash n=$1 d=$2 # because of rounding this should be 10^{i+1} # where i is the number of decimal digits wanted i=4 P=$((10**(i+1))) Pn=$(($P / 10)) # here we 'fix' the decimal place, divide and round tward zero t=$(($n * $P / $d + ($n < 0 ? -5 : 5))) # then we print the number by dividing off the interger part and # using the modulo operator (after removing the rounding digit) to get the factional part. printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn)) 
  • Почему Java Double.compare (double, double) реализован так, как есть?
  • Быстрый метод для округления двойного до 32-битного int
  • Каков самый быстрый способ конвертировать float в int на x86
  • Типы с плавающей запятой с фиксированным размером
  • Почему арифметика с плавающей запятой в C # неточна?
  • Является ли плавающая точка == когда-либо ОК?
  • Почему GCC не оптимизирует a * a * a * a * a * a to (a * a * a) * (a * a * a)?
  • Разница между десятичной, плавающей и двойной в .NET?
  • Сравнение значений с плавающей запятой
  • Почему моя целая математика с std :: pow дает неправильный ответ?
  • проблемы в сравнении с плавающей запятой
  • Interesting Posts

    Проверьте, четное или нечетное число

    RcppArmadillo передает пользовательскую функцию

    PCIE для USB / Thunderbolt для видеокарты

    Как я могу выдать одну команду из командной строки через sql plus?

    Как защитить поле пароля в Mongoose / MongoDB, чтобы он не возвращался в запрос при заполнении коллекций?

    Как записать в буфер памяти с файлом *?

    В Java это результат добавления двух символов int или char?

    Как загрузить последние вкладки в Chrome с помощью файлов Last Tabs, Last Session?

    «Обнаружена ошибка с обнаруженным дефектом» (NTLM не Kerberos) с Kerberos / Spring Security / IE / Active Directory

    Преобразование файлов MP4, AVI, MOV в коллекцию PNG, JPG или GIF кадров

    Является ли создание компьютерного шасси из чистого LEGO опасным?

    Простая реализация C для отслеживания памяти malloc / free?

    Spring Security: как исключить определенные ресурсы?

    Я только что создал свой внешний жесткий диск и дал ему два раздела. Какие файлы они создали? Mac OS X

    Ошибка пропуска в петле

    Давайте будем гением компьютера.