Answers:
在中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,破折号),它受语言环境(可以是.
或的十进制分隔符,
)的影响。
因此,如果浮点数始终以句点作为小数点分隔符来表示,并且printf
无论用户调用脚本的语言环境如何,都希望将其视为此类,则需要将语言环境固定为C:
LC_ALL=C printf '%.0f' "$float"
使用yash
,您还可以执行以下操作:
printf '%.0f' "$(($float))"
(见下文)。
printf "%.0f\n" 1.1
不是POSIX,因为POSIX %f
不需要支持。
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()
math函数,可以为您提供最接近的整数作为浮点数(如中的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是第一个支持浮点运算的类Bourne外壳。当命令仅是内置命令时,ksh93通过不使用管道或分支来优化命令替换。所以
i=$(printf '%.0f' "$f")
不分叉。甚至更好:
i=${ printf '%.0f' "$f"; }
这既不会派生,也不会解决创建伪造的subshell环境的所有麻烦。
您也可以这样做:
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
的数学函数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
int=${float%.*}
在Mac(版本10.13.4(17E199))上的bash(版本3.2.57(1)-发行版)脚本中工作得很好。
,
小数点基数。请参阅有关的部分LC_ALL=C
bc
-任意精度计算器语言
int(float)应该看起来像:
$ echo "$float/1" | bc
1234
为了更好地使用此方法:
$ echo "($float+0.5)/1" | bc
例:
$ float=1.49
$ echo "($float+0.5)/1" | bc
1
$ float=1.50
$ echo "($float+0.5)/1" | bc
2
float=-2; echo "($float+0.5)/1" | bc
给-1
。
之前提交的答案几乎是正确的:“您可以:
float=1.23
int=${float%.*}
但这将删除小数部分,而不是为您提供最接近的整数,并且不适用于$ float的值,例如1.2e9或.12。...”
只需使用${float%%.*}
。
echo ${float%%.*}
1
有关:
补充@StéphaneChazelas awk
答案:
float_to_integer_rounding_nearst() {
awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%.0f", ARGV[i]}' "$@";
}
float_to_integer_rounding_floor() {
awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%d", int( ARGV[i] )}' "$@";
}
printf
是否有所不同,或者是否有其他原因更喜欢awk而不是内置的printf
。