tfto100
tfto100

Reputation: 41

awk calculations giving rounded answers for larger numbers

I have a Linux bash script which is calculating the total of some values in a file using awk. I am using this syntax to do the calculations:

$ awk "BEGIN { print $first_number + $second_number }"

For calculations where the answer is a number below 9999.99, it displays the answer correctly. Above that value, it rounds the answer to one decimal place, or no decimal places, etc. like this:

$ awk "BEGIN { print 89.54 + 6789.44 }"
6878.98

$ awk "BEGIN {print 1.66 + 68790.77 }"
68792.4

$ awk "BEGIN {print 1.66 + 687990.77}"
687992

$ awk "BEGIN {print 10100.66 + 6787990.77}"
6.79809e+06

I want the answer to show the decimals, and to 2 decimal places in all instances.

DO you know why it is doing the unexpected roundings? Thanks

Upvotes: 4

Views: 1922

Answers (3)

Arkku
Arkku

Reputation: 42149

As already answered by others, the problem is with the number formatting: use %.2f with either printf or AWK's OFMT (that applies to print) to get two decimal places.

To pass your shell variables to awk, you can use the -v command-line option, e.g.,

$ awk -v a="$first_number" -v b="$second_number" 'BEGIN {
    printf "%.2f\n", a + b
}'

If you always have exactly two decimal places, you could also use integer arithmetic in bash without the decimal point, and only format the output:

$ printf "%.2f\n" $(( 1010066 + 678799077 ))e-2

(Of course this only works for arithmetic operations that maintain the number of decimals, e.g., addition and subtraction.)

Upvotes: 1

Inian
Inian

Reputation: 85780

Expanding on top of James's useful answer, there is a reason why you see that behavior. It is because the exact manner in which numbers are converted into strings is controlled by a predefined variable in awk called OFMT when using print

OFMT's default value is "%.6g", which creates a value with at most six significant digits. If you want print to represent a more accurate representation, change it for e.g. to always represent 2 digits post the decimal point, something like "%2.2f"

$ awk 'BEGIN { OFMT = "%2.2f"; print 89.54 + 6789.44 }'
6878.98

$ awk 'BEGIN { OFMT = "%2.2f"; print 1.66 + 68790.77 }'
68792.4

$ awk 'BEGIN { OFMT = "%2.2f"; print 1.66 + 687990.77 }'
687992.43

$ awk 'BEGIN { OFMT = "%2.2f"; print 10100.66 + 6787990.77 }'
6798091.43

See here and here, which explains the behavior of these conversions.

Upvotes: 2

James Brown
James Brown

Reputation: 37424

Obviously print is not the right tool to output decimals, use printf and appropriate modifiers:

$ awk 'BEGIN {printf "%.2f\n", 10100.66 + 6787990.77}'
6798091.43

Also, use single quotes ' around the awk program.

Upvotes: 1

Related Questions