Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

awk - round to 2 decimals

Writer Andrew Henderson

I am computing the percentages of every item in a column of a file using the following awk command:

awk '{a[NR]=$2;x+=(b[NR]=$2);c[NR]=$1}END{while(++i<=NR)print c[i]"\t"a[i]"\t"100*b[i]/x"%"}' file.txt > out_file.txt

file.txt

N 38668442
V 14008521
ADJ 16112215 

out_file.txt

N 38668442 56,213%
V 14008521 20,3644%
ADJ 16112215 23,4226%

However, I would like the percentages in the out_file.txt to be rounded to 2 decimals.

desired out_file.txt

N 38668442 56,21%
V 14008521 20,37%
ADJ 16112215 23,42%

Referring to this post:

I tried to integrate printf "%s,%d,%0.2f%\n into my code which raises an argument error even by decreasing the arguments and limit the expression to %0.2f%\n.

 awk '{a[NR]=$2;x+=(b[NR]=$2);c[NR]=$1}END{while(++i<=NR)printf "%s,%d,%0.2f%\n",c[i]"\t"a[i]"\t"100*b[i]/x"%"}' file.txt > out_file.txt

Also bc did not work out. Why does it not produce the desired output? In my opinion, it should work as I found the expression printf "%0.2f\n" in several posts concerning the same issue. Do I miss something trivial?

I greatly appreciate any help or suggestions!

2 Answers

You are misunderstanding the syntax of the printf command (which closely follows that of the underlying C function: see for example man 3 printf for full documentation).

printf takes a format string consisting of a sequence of format specifiers and other literal characters, followed by as many comma-separated arguments as necessary to fill the given format. In your command

printf "%s,%d,%0.2f%\n",c[i]"\t"a[i]"\t"100*b[i]/x"%"

you are telling it to expect 3 values (a %s, a %d, and a %0.2f) but are giving it a single, concatenated, string argument c[i]"\t"a[i]"\t"100*b[i]/x"%". Hence it will run out of arguments during the assignment.

What you presumably intended is

printf "%s\t%d\t%0.2f%%\n", c[i], a[i], 100*b[i]/x

(the tabs go inside the format string; the %% corresponds to a literal % i.e. prevents % from being interpreted as the start of another format specifier).

1

You can also use a function like this which fixes the annoying fact that awk rounds 0.5, etc. down.

function round(number, nDecimals, coef, i)
{ coef = 1 for (i = 1; i <= nDecimals; ++i) { coef *= 10 } number *= coef number >= 0 ? number += 0.5 : number -= 0.5 number = int(number) number /= coef return number
}

Then you can write this to print the input rounded to two decimals:

print round($0, 2)

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy