удар
В bash
, это, вероятно, так же хорошо, как это получается. Это использует встроенную оболочку. Если вам нужен результат в переменной, вы можете использовать подстановку команд или bash
конкретный (хотя теперь также поддерживается zsh
):
printf -v int %.0f "$float"
Вы могли бы сделать:
float=1.23
int=${float%.*}
Но это уберет дробную часть вместо того, чтобы дать вам ближайшее целое число, и это не сработает для значений $float
like 1.2e9
или, .12
например.
Также обратите внимание на возможные ограничения из-за внутреннего представления чисел:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
Вы получаете целое число, но есть вероятность, что вы нигде не сможете его использовать.
Кроме того, как отмечает @BinaryZebra, в нескольких printf
реализациях (bash, ksh93, yash, а не GNU, zsh, dash) на него влияет локаль (десятичный разделитель, который может быть .
или ,
).
Итак, если ваши значения с плавающей точкой всегда выражаются точкой в качестве десятичного разделителя, и вы хотите, чтобы он обрабатывался как таковой printf
независимо от языкового стандарта пользователя, вызывающего ваш скрипт, вам нужно будет установить языковой стандарт на C:
LC_ALL=C printf '%.0f' "$float"
С помощью yash
вы также можете сделать:
printf '%.0f' "$(($float))"
(Смотри ниже).
POSIX
printf "%.0f\n" 1.1
не POSIX, так как %f
не требуется для поддержки POSIX.
POSIXly, вы можете сделать:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
На него не влияет языковой стандарт (запятая не может быть десятичным разделителем, awk
поскольку там уже есть специальный символ в синтаксисе ( print 1,2
аналогично print 1, 2
передаче двух аргументов print
)
ЗШ
В zsh
(которая поддерживает арифметику с плавающей запятой (десятичный разделитель всегда является точкой)), у вас есть rint()
математическая функция, которая дает вам ближайшее целое число в виде числа с плавающей запятой (как в C
) и int()
дает вам целое число из числа с плавающей запятой (как в awk
). Так что вы можете сделать:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
Или же:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
Однако обратите внимание, что хотя double
s может представлять очень большие числа, целые числа гораздо более ограничены.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
ksh93 была первой подобной Борну оболочкой, которая поддерживает арифметику с плавающей запятой. ksh93 оптимизирует подстановку команд, не используя канал или разветвление, когда команды являются только встроенными командами. Так
i=$(printf '%.0f' "$f")
не развивается Или даже лучше:
i=${ printf '%.0f' "$f"; }
который также не работает, но также не создает проблем при создании поддельной оболочки.
Вы также можете сделать:
i=$((rint(f)))
Но остерегайтесь:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
Вы также можете сделать:
integer i=$((rint(f)))
Но, как для zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Помните, что ksh93
арифметика с плавающей запятой учитывает настройку десятичного разделителя в локали (хотя ,
в противном случае это математический оператор ( $((1,2))
будет 6/5 во французской / немецкой ... локали, и то же самое $((1, 2))
, что 2 в английской локали) ,
йаш
йаш также поддерживает арифметику с плавающей , но не имеет математические функции , такие как ksh93
/ zsh
«s rint()
. Вы можете преобразовать число в целое число, используя, например, двоичный файл или оператор (также работает в, zsh
но не в ksh93
). Обратите внимание, что он усекает десятичную часть, но не дает ближайшего целого числа:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash
учитывает десятичный разделитель локали при выводе, но не для литеральных констант с плавающей запятой в их арифметических выражениях, что может вызвать неожиданность:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
Это хорошо в том смысле, что вы можете использовать константы с плавающей запятой в ваших скриптах, которые используют точку, и вам не нужно беспокоиться о том, что она перестанет работать в других локалях, но при этом сможете обрабатывать числа, выраженные пользователем до тех пор, пока как вы не забыли сделать:
var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".
printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3