Is this the right way to do float to integer conversion in bash? Is there any other method?

flotToint() {
    printf "%.0f\n" "$@"
  • 5
    What is "right"?
    – Joseph R.
    Sep 6, 2013 at 21:40
  • 1
    I just want to make sure.. is this right or is there better than this ? Sep 6, 2013 at 21:41
  • 4
    %.0f will round up or down. Is that what you want? You can use printf "%d\n" "$@" 2>/dev/null to chop the fraction.
    – ott--
    Sep 6, 2013 at 23:56

5 Answers 5



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 the bash specific (though now also supported by zsh):

printf -v int %.0f "$float"

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 like 1.2e9 or .12 for instance.

Also note the possible limitations due to the internal representation of floats:

$ printf '%.0f\n' 1e50

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 zsh, dash or older version of GNU printf), it is affected by the locale (the decimal separator which could 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:

LC_ALL=C printf '%.0f' "$float"

With yash, you can also do:

printf '%.0f' "$(($float))"

(see below).


printf "%.0f\n" 1.1

is not POSIX as %f is not required to be supported by POSIX.

POSIXly, you can do:

f2i() {
  LC_ALL=C awk -- '
    BEGIN {
      for (i = 1; i < ARGC; i++)
        printf "%.0f\n", ARGV[i]
    }' "$@"

Note that though literal numbers in the awk language syntax are always using the . as decimal radix character (as , is used to separate arguments so couldn't be used in numbers), when taking numbers on input like here from ARGV, some implementations honour the locale's decimal radix character. In the case of GNU awk, that's only when $POSIXLY_CORRECT is in the environment.


In zsh (which supports floating point arithmetic (decimal separator is always the period)), you have the rint() math function to give you the nearest integer as a float (like in C) and int() to give you an integer from a float (like in awk). So you can do:

$ zmodload zsh/mathfunc
$ i=$(( int(rint(1.234e2)) ))
$ echo $i


$ integer i=$(( rint(5.678e2) ))
$ echo $i

However note that while doubles can represent very large numbers, integers are much more limited.

$ printf '%.0f\n' 1e123
$ echo $((int(1e123)))


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

i=$(printf '%.0f' "$f")

doesn't fork. Or even better:

i=${ printf '%.0f' "$f"; }

which doesn't fork either but also doesn't go all the trouble of creating a fake subshell environment.

You can also do:

i=$(( rint(f) ))

But beware of:

$ echo "$(( rint(1e18) ))"
$ echo "$(( rint(1e19) ))"

You could also do:

integer i=$(( rint(f) ))

But like for zsh:

$ integer i=1e18
$ echo "$i"
$ integer i=1e19
$ echo "$i"

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 also supports floating point arithmetic but doesn't have math functions like ksh93/zsh's rint(). You can convert a number to integer though by using the binary or operator for instance (also works in zsh but not in ksh93). Note however that it truncates the decimal part, it doesn't give you the nearest integer:

$ echo "$(( 0.237e2 | 0 ))"
$ echo "$(( 1e19 | 0 ))"

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:

$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator

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:

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%.*} worked very well in my bash (version 3.2.57(1)-release) script on a Mac (version 10.13.4 (17E199)). Jun 7, 2018 at 6:47
  • You first formulation fails in GNU bash 4.4.19, e.g.: ``` $ echo $maximum 32.800 $ printf -v int %.0f "$maximum" bash: printf: 32.800: invalid number ``` Mar 1, 2019 at 8:55
  • @LuísdeSousa, your locale probably has , as the decimal radix. See the section about LC_ALL=C Mar 1, 2019 at 9:03
  • Note that this answer answers a different question: How to remove digits after the dot not what was asked: what's the right way of doing float to integer.
    – user232326
    Oct 13, 2019 at 16:33
  • Should this method applied to floats of any number of bits? Should it be the same for a float of 23 bits or 128 bits mantissa?
    – user232326
    Oct 13, 2019 at 16:35

bc - An arbitrary precision calculator language

int(float) should looks like:

$ echo "$float/1" | bc 

To round better use this:

$ echo "($float+0.5)/1" | bc 


$ float=1.49
$ echo "($float+0.5)/1" | bc 
$ float=1.50
$ echo "($float+0.5)/1" | bc 

A very simple hacky one is

function float_to_int() { 
  echo $1 | cut -d. -f1    # or use -d, if decimals separator is ,

Sample output

$ float_to_int 32.333
$ float_to_int 32
  • 1
    It'd be possible to use sed, but cut solution is simpler. I prefer sed or cut as they are IMHO more available on embedded targets than awk (which is still quite common via busybox than bc).
    – pevik
    Sep 19, 2019 at 10:22

The previous answer submitted was almost correct: "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 like 1.2e9 or .12 for instance...."

Just use ${float%%.*}.

echo ${float%%.*}
  • The only way ${float%%.*} could be different from ${float%.*} would be if $float contained more than one occurrence of .. That still gives you 1 for 1.99, the empty string for .12 and 2 for 2.2e9, so it doesn't help at all. Also remember that parameter expansions must be quoted in list contexts in Bourne-like shells. May 16, 2021 at 10:38


  1. how make float to integer in awk,
  2. How to round floating point numbers in shell?

Complementing @Stéphane Chazelas awk answer:

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] )}' "$@";
  • on my awks, the latter one rounds towards zero, not to minus infinity (as "floor" can be taken to mean). Also, the first rounds halves to even numbers. I'm not sure if that's any different from what Bash's printf does, or if there's any other reason to prefer awk over the builtin printf.
    – ilkkachu
    Oct 13, 2019 at 16:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .