Upon printing, non-integer numbers are converted to decimal string representation using the OFMT
special variable which contains a printf
format specification (by default %.6g
). You can change it to %.17g
to get the maximum precision of IEEE 754 double precision binary floating point numbers (as used internally by most awk
implementations on most systems). Another variable (CONVFMT
) is used in the other cases where a floating point numbers are implicitly converted to strings (like when you concatenate a number with something else)
You won't get more precision with those doubles, there's no point going beyond 17. Already with 17, you're likely to see some artifacts. 15 significant digits may be better if you don't need that much precision.
$ awk -v OFMT=%.17g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981000000008
$ awk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981
While OFMT
affects all printed floating point numbers, you could also use printf
directly to print numbers with the required precision.
$ awk -F ',' '{SUM+=$2};END{printf "%.15g\n", SUM}' < file
6.7088981
The GNU implementation of awk
, since version 4.1.0 can also be compiled with arbitrary precision arithmetics support (see info gawk 'Arbitrary Precision Arithmetic'
). If that's the case on your system, you could also do:
gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}' < file
Example:
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}'
999999999999999945575230987042816
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}'
1000000000000000000000000000000001.00000000001
Another approach here could be to use bc
(assuming those numbers are always expressed like that (0.001
, not 1e-3
for instance)):
<file tail -n+2 | # skip header
cut -d, -f2 | # extract second field
paste -sd + - | # join input lines with +
bc
The number of digits after the .
will be the maximum in any input record.
awk -F ',' '{SUM+=$2}END{printf "%.20f\n", SUM}' file
and you'll get an output like6.70889810000000075263
OFMT
(which is%.6g
iirc). See related awk to sum the numbers(floating) and group it on a unique key