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

8 comments:

JP said...

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

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

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

Jadu Saikia said...

@JP, thanks. Its helpful.

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.

// Jadu

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.

Jadu Saikia said...

@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.

Jadu Saikia said...

@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.

© Jadu Saikia www.UNIXCL.com