Округление числа с плавающей точкой bash

Итак, я пытаюсь округлить ввод 17.92857, так что он получает вход 17.929 в баш.

Мой код до сих пор:

read input
echo "scale = 3; $input" | bc -l

Однако, когда я использую это, оно не округляется, а возвращается 17.928,

Кто-нибудь знает какие-либо решения для этого?

4 ответа

Решение

В случае input содержит число, нет необходимости во внешней команде, такой как bc, Вы можете просто использовать printf:

printf "%.3f\n" "$input"

Изменить: В случае если формула ввода, вы должны использовать bc как в одной из следующих команд:

printf "%.3f\n" $(bc -l <<< "$input")
printf "%.3f\n" $(echo "$input" | bc -l)

Вы можете написать вспомогательную функцию оболочки round ${FLOAT} ${PRECISION} за это:

#!/usr/bin/env bash

round() {
  printf "%.${2}f" "${1}"
}

PI=3.14159

round ${PI} 0
echo
round ${PI} 1
echo
round ${PI} 2
echo
round ${PI} 3
echo
round ${PI} 4
echo
round ${PI} 5
echo
round ${PI} 6
echo

# Outputs:
3
3.1
3.14
3.142
3.1416
3.14159
3.141590

# To store in a variable:
ROUND_PI=$(round ${PI} 3)
echo ${ROUND_PI}

# Outputs:
3.142

Даже если Тим уже ответил в 2014 году, я хочу поделиться улучшенной версией функции Зейна.

#!/usr/bin/env bash

# round a float number to the given decimal digits
# if $2 is not given or not a positive integer its set to zero

# float must be in international format, this is more save for scripts
# to use other format replace LC_ALL=C with your language.

_round_float() {
     local digit="${2}"; [[ "${2}" =~ ^[0-9]+$ ]] || digit="0"
     LC_ALL=C printf "%.${digit}f" "${1}"
}

несколько примеров использования функции:

# round pi constant
PI=3.141599236

_round_float $PI 0   3
_round_float $PI 1   3.1
_round_float $PI 3   3.142
_round_float $PI 9   3.141599236
_round_float $PI -3  3
_round_float $PI abc 3

вы также можете настроить положение запятой, то есть делить / умножать на 10 на лету

 #!/bin/bash
 # change metric base unit
 UNIT=1234.567890

 # comma 1 position right, multiply by 10
 _round_float ${UNIT}e1 3     12345.678

 # comma 3 positions left, eg convert milli seconds to seconds
 _round_float ${UNIT}e-3 3     1.234

 # comma 3 positions right, eg convert m3 to liters
 _round_float ${UNIT}e3 0     1234567

Небольшая хитрость, чтобы добавить 0.0005 к вашему входу, таким образом, ваш номер будет правильно округлен.

Если вы получаете ошибку округления с числом 17,928, попробуйте это: read y v=echo "scale = 3; $y" |bc -lесли [ $v == 17,928 ]; тогда эхо "17.929", еще эхо $ V Fi

Другие вопросы по тегам