Awk - Round to 2 Decimals

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

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

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest