Monday, January 5, 2009

Round functionality with awk - bash shell

As there is no standard "round" function available in awk, some of the ways to round float values to the rounded integer.

\$ echo "23.54" | awk '{printf("%d\n",\$1 + 0.5)}'
24

\$ echo "23.49" | awk '{printf("%d\n",\$1 + 0.5)}'
23

Lets make this a function named round.

\$ echo "23.54" | awk '
function round(A) {
return int( A + 0.5 )
}
{
printf("%d\n",round(\$1));
}'
24

Another way:

\$ echo "23.54" | awk '{printf("%d\n",\$0+=\$0<0?-0.5:0.5)}'
24

Related post:
round float values using sprintf in awk

JP said...

Why bother with awk? 'printf' is a bash builtin:

\$ printf "%.0f\n" "23.54"
24

\$ printf "%.0f\n" "23.44"
23

The reason I tried with awk (using printf though), as my original intention was to round only one field(column) out of several columns of a delimited file(as shown in the related post link in the post). Thanks for posting.

stinkinrich88 said...

Note that this solution does not work with negative numbers. Use JP's suggestion in awk to cover both positive and negative numbers.

@stinkinrich88, thanks for pointing this.

Jim Mellander said...

With a little added coding you can specify the number of decimal places, as well as deal with negative numbers:

function round(num,places, sign) {
# Rounds to /places/ decimal points - if /places/ not supplied it is
# treated as 1, also can supply negative /places/
places=10^places
sign=1
if (num < 0) {sign = -1; num = -num;}
return sign * int(num*places + .5)/places
}

Raluca Brez said...

Hi,
I am having some trouble on rounding to nearest minute.

I have a file with different values. One of the columns is time.

Ex.:
0:0:17
0:1:18
0:2:19
0:19:33
0:26:49

What I need to do is rounding up and down depends on the number of seconds (if up to 30 then rounding down, if more then 30 rounding up). So 0:0:17 will become 00:00 and 0:26:49 will become 00:27.

I mention that I am on a bash shell.

Thank you,
R.

@Raluca Brez , thanks for the question. I can quickly think of this:

\$ cat file.txt
0:0:17
0:1:18
0:2:19
0:19:33
0:26:49

\$ awk -F ":" 'BEGIN {OFS=":"}{if(\$NF>30) {\$2+=1}{print \$1,\$2}}' file.txt

0:0
0:1
0:2
0:20
0:27

Hope this helps. Thanks.

Raluca Brez said...

Hi, thank you for you quick response, Yes, that was very useful. Thanks again.