баш
В bash
, мабуть, це так добре, як це виходить. Тут використовується вбудована оболонка. Якщо вам потрібен результат у змінній, ви можете використовувати підстановку команд або bash
специфічну (хоча зараз це також підтримується zsh
):
printf -v int %.0f "$float"
Ви можете зробити:
float=1.23
int=${float%.*}
Але це видалить дробову частину замість того, щоб дати вам найближче ціле число, і це не працюватиме для значень $float
типу 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
кш93
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 в англійській мові) .
яш
yash також підтримує арифметику з плаваючою комою, але не має математичних функцій, як 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