Округление числа с плавающей точкой 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