баш
В 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
Однак зауважте, що хоча doubles може представляти дуже великі числа, цілі числа значно обмежені.
$ 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/ zshs 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