Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Is this right way of doing float to integer in bash, Or is there any other method ?

flotToint() {
    printf "%.0f\n" "$@"
share|improve this question
What is "right"? – Joseph R. Sep 6 '13 at 21:40
I just want to make sure.. is this right or is there better than this ? – Rahul Patil Sep 6 '13 at 21:41
%.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 '13 at 23:56

3 Answers 3

up vote 25 down vote accepted


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:

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 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:

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

With yash, you can also do:

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

for the content of $float to be converted to the format in the current locale.


printf "%.0f\n" 1.1

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

POSIXly, you can do:

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

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 as print 1, 2 to pass two arguments to print)


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.

You can also do:


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))"

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
share|improve this answer
Thanks for sharing :) – Khushal Dave Aug 11 '14 at 22:09
@BinaryZebra. Thanks, I've updated it with some more information on the influence of the locale wrt the decimal point. – Stéphane Chazelas Oct 29 at 15:09
Thanks again @BinaryZebra. The worst thing is that I was already told off about it not so long ago. – Stéphane Chazelas Nov 2 at 9:55

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 
share|improve this answer
But float=-2; echo "($float+0.5)/1" | bc gives -1. – Stéphane Chazelas Aug 12 '14 at 6:21
That is called round towards +inf. That is one of four possible ways to round. – BinaryZebra Nov 1 at 20:20

install the beep program with:

aptitude install beep
apt-get install beep

and listen to the sine function like this:

1a. define the function in bash:

$ function sinus () 
    d=$(echo "scale=$f; ($b-$a)/$n"|bc);
    for m in $(seq 0 $n);
        x=$(echo "scale=$f;$a+$m*$d"|bc);
        y=$(echo "scale=$f;s($x)"|bc -l);
        #printf "%0.${f}f\t" "$x";
        #printf "%0.${f}f\n" "$y";
        z=$(echo "scale=$f; 2300+2000*$y" | bc);
        beep -f "$z" -l 2 -d 0;
    done | column -t

2a. Call this function like this:

$ sinus 1 20 300 4

Note: 'sinus a b n f' means to listen the sound of sine (in radians) from a to b dividing the interval in n+1 equal parts using f decimals. There are more things than needed in the function because you can use them to plot or any other things. You can also write read a b n f instead of the initializations.

Also, very funny, crushing the cycles in the sine function more and more until the program can't stand it:

1b. define:

$ function sinus-inv () 
    a=$1; b=$2; n=$3; f=$4;
    d=$(echo "scale=$f; ($b-$a)/$n"|bc);
    for m in $(seq 1 $n);
        x=$(echo "scale=$f;$a+$m*$d"|bc);
        y=$(echo "scale=$f;s(8000/($b-$x))"|bc -l);
        z=$(echo "scale=$f; 2300+2000*$y" | bc);
        beep -f "$z" -l 1 -d 0;

2b. Example call:

$ sinus-inv 1 100 1000 8
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.