bash НЕ умеет в float

Если нужно выполнить float выражения, можно использовать сторонние утилиты. Как один из вариантов, сделать функцию fp с таким содержанием:

function fp {
    # fp - реализация операций с плавающей точкой через awk
    # usage: fp "выражение"
    local args="${*:-}"
    awk "BEGIN { print $args }"
}

Арифметика в двойных круглых скобках (( ))

Это best practices для арифметики в bash I think

В двойных круглых скобках (( )) выполняются арифметические вычисления. Внутри (( )) не требуются $ перед именами переменных. Их можно встретить в цикле for или в if:

for ((i=0; i<size; i++)); do :; done
if (( max - 3 > x * 4 )); then :; fi

Результат выражения можно присвоить переменной, добавив $:

max="$(( intro + body + outro - 1 ))"
median_loc=$((len / 2))

В операторе if $ не нужен, т.к. там для принятия решения достаточно булевых значений. Если при вычислении выражения в двойных круглых скобках (без $) получается ненулевой результат возвращается статус 0 (true), иначе - статус 1 (false).
(( )) без $ интерпретируются как выполнение одной/нескольких команд, которые не возвращают результат вычислений. Хоть и есть исключения:

# Bash поддерживает некоторые C-like операторы присваивания
(( step ++ ))
(( median_loc = len / 2 ))
(( dist *= 4 ))

Выражения выше всё равно не возвращают ничего (кроме кода возврата в $?), а только присваивают значение переменным. Их можно оформить и так:

step="$(( step ++ ))"
median_loc="$(( median_loc = len / 2 ))"
dist="$(( dist *= 4 ))"

Не юзай "$((step++))" как самостоятельную инструкцию в отдельной строке

Такие выражения опасно юзать как самостоятельные инструкции, ибо они будут возвращать числа (из-за $), которые интерпретатор воспримет как имя какой-то команды: если, например, выражение вернет 3 оболочка попытается запустить команду с именем 3.

Однако внутри круглых скобок пробелы допускаются, ибо круглые скобки определяют границы этого “слова”.

Пару слов о let

Раньше вместо (( )) использовали (и используют) встроенную команду let:

# Эквивалентные выражения
(( step ++ ))
let "step++"
 
(( median_loc = len / 2 ))
let "median_loc = len / 2"
 
(( dist *= 4 ))
let "median_loc = len / 2"

Выражение let бери в кавычки

let принимает только одно “слово”, а пробелы в выражении разделяют выражение на несколько слов (чревато синтаксической ошибкой), и чтобы не было ошибок арифметическое выражение заключай в кавычки.

”Голая” арифметика

Есть один не очень желательный способ выполнения арифметических вычислений без использования (( )) или let суть в объявлении заранее переменной как integer, после которого можно будет с переменной выполнять арифметические вычисления без (( )) или let:

declare -i SEE
X=9
Y=3
 
SEE=X+Y    # 12  (интерпретируется как АРИФМЕТИЧЕСКАЯ операция)
SAW=X+Y    # X+Y (интерпретируется как СТРОКОВЫЙ литерал)
SUU=$X+$Y  # 9+3 (интерпретируется как КОНКАТЕНАЦИЯ строк)

Такой стиль выполнения арифметических действий чреват ошибками, ибо:

  1. Можно просто забыть объявить переменную как целочисленную
  2. Оболочка не сообщит об “ошибке”
  3. Не очень очевидно в коде будет, какая из переменных integer

Соус: Книга Идиомы Bash Глава 5. Выражения и арифметика