Is this the right way to do float to integer conversion in bash? Is there any other method?
flotToint() {
printf "%.0f\n" "$@"
}
bashfloating pointnumeric data
Is this the right way to do float to integer conversion in bash? Is there any other method?
flotToint() {
printf "%.0f\n" "$@"
}
Best Answer
bash
In
bash
, that's probably as good as it gets. That uses a shell builtin. If you need the result in a variable, you could use command substitution, or thebash
specific (though now also supported byzsh
):You could do:
But that would remove the fractional part instead of giving you the nearest integer and that wouldn't work for values of
$float
like1.2e9
or.12
for instance.Also note the possible limitations due to the internal representation of floats:
You do get an integer, but chances are that you won't be able to use that integer anywhere.
Also, as noted by @BinaryZebra, in several
printf
implementations (bash, ksh93, yash, not GNU, zsh, dash), it is affected by the locale (the decimal separator which can be.
or,
).So, if your floats are always expressed with the period as the decimal separator and you want it to be treated as such by
printf
regardless of the locale of the user invoking your script, you'd need to fix the locale to C:With
yash
, you can also do:(see below).
POSIX
is not POSIX as
%f
is not required to be supported by POSIX.POSIXly, you can do:
That one is not affected by the locale (the comma cannot be a decimal separator in
awk
since it's already a special character in the syntax there (print 1,2
, same asprint 1, 2
to pass two arguments toprint
)zsh
In
zsh
(which supports floating point arithmetic (decimal separator is always the period)), you have therint()
math function to give you the nearest integer as a float (like inC
) andint()
to give you an integer from a float (like inawk
). So you can do:Or:
However note that while
double
s can represent very large numbers, integers are much more limited.ksh93
ksh93 was the first Bourne-like shell to support floating point arithmetic. ksh93 optimises command substitution by not using a pipe or forking when the commands are only builtin commands. So
doesn't fork. Or even better:
which doesn't fork either but also doesn't go all the trouble of creating a fake subshell environment.
You can also do:
But beware of:
You could also do:
But like for
zsh
:Beware that
ksh93
floating point arithmetic honour the decimal separator setting in the locale (even though,
is otherwise a math operator ($((1,2))
would be 6/5 in a French/German... locale, and the same as$((1, 2))
, that is 2 in an English locale).yash
yash also supports floating point arithmetic but doesn't have math functions like
ksh93
/zsh
'srint()
. You can convert a number to integer though by using the binary or operator for instance (also works inzsh
but not inksh93
). Note however that it truncates the decimal part, it doesn't give you the nearest integer:yash
honours the locale's decimal separator on output, but not for the floating point literal constants in its arithmetic expressions, which can cause surprises:It's good in a way in that you can use floating point constants in your scripts that use the period and not have to worry that it will stop working in other locales, but still be able to deal with the numbers as expressed by the user as long as you remember to do: