Сравнение плавающих чисел с использованием BC - PullRequest
1 голос
/ 05 августа 2020

Фон

Здесь новичок пытается изучить некоторые Bash основы.

Мой вопрос - это моя попытка изменить существующий пример из учебника, чтобы включить простую проверку ввода. Проверка работает, если один или несколько входов не подходят, но когда все три входа подходят, я вместо этого получаю предупреждение об ошибке синтаксиса, а затем ответ.

Код в конце, но ниже мои мысли. Цените любые исправления, где бы они ни были. Большое спасибо.

Мысли

  • У меня есть три условия, которые нужно проверить. Если какой-либо из них выходит из строя, отображается сообщение и программа завершается. Это работает. Однако, если все 3 условия выполнены, я получаю синтаксическую ошибку.
  • Я думал, что ошибка может быть связана с расширением, поэтому я вручную запустил команды и ввел жесткие данные с помощью командной строки. Например, bc <<< "0.5 > 0", и они, похоже, работали так, как задумано.
  • Впоследствии кажется, что мои проблемы возникают только тогда, когда я использую переменную $ Interest с ее десятичными точками. Однако я использовал B C, потому что, как я понимаю, Bash работает только с целыми числами. Что еще я пропустил?

Код

# loan-calc: script to calculate monthly loan payments
#               formulae may be mathematically wrong, example copied from textbook
#               reference only for bash scripting, not math

PROGNAME="${0##*/}"

usage () {
    cat <<- EOF
    Usage: $PROGNAME PRINCIPAL INTEREST MONTHS

    Where:
    PRINCIPAL is the amount of the loan.
    INTEREST is the APR as a number (7% = 0.07)
    MONTHS is the length of the loan's term.

    EOF
}

read -p "Enter principal amount > " principal

read -p "Enter interest rate (E.g. 7.5% = 0.075) > " interest

read -p "Enter term length in months > " months

# Principal, interest rate, and months must be more than 0.
if (( "$principal <= 0" | bc )) || (( "$months <= 0" | bc )) || (( "$interest <= 0" | bc )); then
    usage
    exit 1
fi

result=$(bc <<- EOF
    scale = 10
    i = $interest / 12
    p = $principal
    n = $months
    p * ((i * ((1 + i) ^ n)) / (((1 + i) ^ n) - 1))
EOF
)

printf "%0.2f\n" $result

1 Ответ

0 голосов
/ 05 августа 2020

Shell Arithmeti c

(( 1 | bc )) не переводит 1 в bc. Когда вы оцениваете выражения внутри (( expression )), | - это побитовый оператор OR, не канал .

(( bc )) каждый раз оценивается как 1 , поэтому все ваши условные тесты просто объединяют число с помощью ИЛИ с 1, не переводят число в bc.

Ваше выражение внутри круглых скобок должно быть результатом повторения математическая строка в bc с использованием конвейера, например (( $(echo "$variable <= 0"| bc) )).

Это может быть заключено в именованную функцию, чтобы выражение if было более читабельным.

notValid() {
    (( $(echo "$1 <= 0" | bc) ))
}

# Principal, interest rate, and months must be more than 0.
if  notValid "$principal" || notValid "$months" || notValid "$interest"; then
    usage
    exit 1
fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...