Alex
Alex

Reputation: 297

AWK sum of large integers

I am trying to sum a list of integers from a logfile using awk

{sum+=$1} END {print sum}

The problem is that the result is larger than the MAX_INT specified in my limits.h file, so the print returns 3.68147e+09

Is there an elegant way of printing the entire value of the sum?

Thank you!

Upvotes: 6

Views: 6194

Answers (4)

Kent
Kent

Reputation: 195179

gnu awk has -M option, you can try with it. it should keep the precision for you.

The MPFR and MP libraries should be used when you compile gawk, not at run time.

here is an example, with or without -M. tested with gawk 4.1.0 on 64bit linux (Archlinux):

kent$  awk 'BEGIN{printf "%d\n","368147000099999999999999999999999999"}'  
368147000099999983291776543710248960

kent$  awk -M 'BEGIN{printf "%d\n","368147000099999999999999999999999999"}'
368147000099999999999999999999999999

Upvotes: 5

devnull
devnull

Reputation: 123608

You could use bc which supports arbitrary precision arithmetic. The equivalent of what you're trying to achieve would be:

cut -d' ' -f1 inputfile | paste -sd+ | bc -l

EDIT: As per your comment, if you want to prevent splitting of output into multiple lines, set BC_LINE_LENGTH to 0. Say:

cut -d' ' -f1 inputfile | paste -sd+ | BC_LINE_LENGTH=0 bc -l

Upvotes: 1

vishal_g
vishal_g

Reputation: 3931

I'm pretty sure that AWK uses double, internally, for arithmetic, so beyond a certain limit, you're going to loose precision.

Have a look on this link if it helps you out.

Adding large number using AWK issue cases

Upvotes: 0

Amadan
Amadan

Reputation: 198436

awk does not have integral type that is large enough for your data, and promotes the sum into floating point. As far as I know, there is no data type in awk with enough precision for what you ask. I.e. the problem is not in printing; awk literally does not have the information you want.

You can try ruby instead, for example (it promotes integers into big integers rather than into floats):

ruby -nae 'BEGIN{sum=0}; END{puts sum}; sum+=$F[0].to_i'

Upvotes: 3

Related Questions