«Недопустимый арифметический оператор» при выполнении математических операций с плавающей запятой в bash

#linux #bash #shell

#bash #оболочка #unix #математика

Вопрос:

Вот мой сценарий:

 d1=0.003
d2=0.0008
d1d2=$((d1   d2))

mean1=7
mean2=5
meandiff=$((mean1 - mean2))

echo $meandiff
echo $d1d2
  

Но вместо того, чтобы получить мой предполагаемый результат:

 0.0038
2
  

Я получаю сообщение об ошибке Invalid Arithmetic Operator, (error token is ".003")?

Комментарии:

1. Кстати, если вы переключились с bash на ksh93, плавающая точка будет доступна изначально.

Ответ №1:

bash не поддерживает арифметику с плавающей запятой. Вам нужно использовать внешнюю утилиту, например bc .

 # Like everything else in shell, these are strings, not
# floating-point values
d1=0.003
d2=0.0008

# bc parses its input to perform math
d1d2=$(echo "$d1   $d2" | bc)

# These, too, are strings (not integers)
mean1=7
mean2=5

# $((...)) is a built-in construct that can parse
# its contents as integers; valid identifiers
# are recursively resolved as variables.
meandiff=$((mean1 - mean2))
  

Комментарии:

1. Это просто не так . bash не был написан с поддержкой арифметики с плавающей запятой.

Ответ №2:

Другой способ вычисления чисел с плавающей запятой — это использование возможности округления AWK, например:

 a=502.709672592
b=501.627497268
echo "$a $b" | awk '{print $1 - $2}'

1.08218
  

Комментарии:

1. Этот ответ намного лучше.

2. Отличная альтернатива.

3. для меня команда bc отсутствовала в сборке yocto. awk — это спасение жизни. Спасибо 🙂

Ответ №3:

В случае, если вам не нужна точность с плавающей запятой, вы можете просто удалить десятичную часть.

echo $var | cut -d "." -f 1 | cut -d "," -f 1

вырезает целочисленную часть значения. Причина использования cut twice заключается в разборе целочисленной части на случай, если региональные настройки могут использовать точки для разделения десятичных дробей, а некоторые другие могут использовать запятые.

Редактировать:

Или, для автоматизации региональных настроек, можно использовать locale .

echo $var | cut -d $(locale decimal_point) -f 1

Комментарии:

1. На самом деле, вам, вероятно, следует проверить правильный разделитель. Если вы просто сократите оба, это может быть действительно плохо с некоторыми (т. Е. С НАМИ?) Стандартами наличия запятой для тысяч и точек для десятичных дробей. Ваш скрипт сократится 1,005.3 до 1 вместо 1005.

2. @bufu Конечно. На самом деле это можно проверить через locale. Я обновлю свой ответ.

3. Я не знал locale , что для этого есть a. Имейте мой голос, добрый сэр!

Ответ №4:

Вы можете изменить оболочку, которую вы используете. Если вы выполняете свой скрипт с помощью оболочки bash bash scriptname.sh , попробуйте использовать ksh для выполнения вашего скрипта. Bash не поддерживает арифметические операции, которые включают числа с плавающей запятой.

Ответ №5:

Большое bc спасибо команде — это полностью спасло мой день! Это простой ответ, но он сработал как шарм.

 a=1.1
b=1.1

echo $a   $b | bc -l
# Output:
2.2

#SUM
sum=$(echo $a   $b | bc -l) 
echo $sum
# Output
2.2
  

bc это калькулятор командной строки, который позволяет пользователям выполнять математические вычисления на терминале.