
tengo escenario
¿Dónde tengo un problema porque UNIX suma hasta 8 a 9 escalas y me da una suma incorrecta? ¿Cómo solucionarlo?
mi comando usado
awk -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
Este es el enlace a la pregunta anterior publicada. ¿Por qué hay una diferencia entre estos dos comandos de suma?
¿Hay alguna forma mejor de abordarlo para poder obtener la suma exacta?
usando awk o bc o dc
Datos de demostración
1|"12.8"|demo1
2|"13.5678341234567"|demo1
3|"14.578"|demo1
4|"15.58"|demo1
5|"16.56784"|demo1
6|"17.578"|demo1
7|"18.678"|demo1
8|"19.568890123"|demo1
9|"20.588792"|demo1
Respuesta1
No dice el tamaño del archivo (es decir, cuántas filas está agregando). La descarga requirió 18,3 MB antes de que el sitio apareciera como "Peligroso" y "Alerta de fraude". Si la longitud promedio de fila es 18, se agregan un millón de flotantes y no conocemos el intervalo de valores. El total que muestra en la pregunta es de 13,2 dígitos, por lo que el valor promedio por línea ronda los 7 dígitos, con variabilidad desconocida.
Si sigues sumando valores como 27.865326635297 a un total acumulado que se acerca a los 13 dígitos enteros, entonces solo la parte 27.87 (redondeada) llegará al total porque el .00532... está fuera del 15 o Rango de resultados de 16 dígitos. A veces esos errores se cancelan, otras no: la aritmética de Montecarlo.
Verifique el resultado de awk --version. Si menciona MPFR y MP, su awk se compila con matemáticas de precisión extendida. Simplemente agrega -M 113 a tu comando awk. Esa es la longitud de la mantisa que le brinda una precisión cuádruple en aritmética real: precisión de 33 dígitos.
www.gnu.org/software/gawk/manual/gawk.html#Arbitrary-Precision-Arithmetic
Respuesta2
Este es un método basado en lacorriente continuacomando (suponiendo que esto tenga la precisión adecuada compilada). Viste la segunda columna con comandos dc y funciona con una precisión de 60 dígitos (200 bits).
Esto se ejecuta en las 10 líneas de datos proporcionadas anteriormente, más un par de valores extremos. Muestra sumas intermedias: para eliminarlas, elimine la 'p' justo antes de \n donde awk emite $2.
Paul--) cat awkToDc
#! /bin/bash
function Data { cat <<'EOF'
1|"12.8"|demo1
2|"13.5678341234567"|demo1
3|"14.578"|demo1
4|"15.58"|demo1
5|"16.56784"|demo1
6|"17.578"|demo1
7|"18.678"|demo1
8|"19.568890123"|demo1
9|"20.588792"|demo1
10|"55555555555555555555000000000000"|demo1
11|"20.588792"|demo1
12|"0.000000000000000000077777777777"|demo1
EOF
}
function dataDC {
AWK='
BEGIN { FS = "\042"; printf ("60 k 0\n"); }
{ printf ("%s + p\n", $2); }
END { printf ("p q\n"); }
'
awk "${AWK}"
}
Aclaración sobre los comandos dc emitidos (que están en notación polaca inversa):
'60 k' establece la precisión aritmética y '0' inicializa el total.
' +' suma el valor de $2 al total. 'p' imprime el total acumulado a modo ilustrativo.
'p q' imprime el total final y sale.
Data | dataDC | dc
Paul--) ./awkToDc
12.8
26.3678341234567
40.9458341234567
56.5258341234567
73.0936741234567
90.6716741234567
109.3496741234567
128.9185642464567
149.5073562464567
55555555555555555555000000000149.5073562464567
55555555555555555555000000000170.0961482464567
55555555555555555555000000000170.096148246456700000077777777777
55555555555555555555000000000170.096148246456700000077777777777
Paul--)
Ahora tenga cuatro técnicas probadas (contra su archivo de prueba de 722277 filas), con índices de precisión.
Al usar gawk con una precisión de 200 bits y dc con una precisión de 60 dígitos, ambos coinciden en el mismo total de 33 dígitos, que sospecho que es exacto.
25396577843.7560139069641121618832
El uso de gawk con precisión estándar IEEE (debe ser de 15 o 16 dígitos) solo concuerda con los primeros 12 de esos dígitos. Supongo que un millón de adiciones erosionan la precisión a medida que los exponentes se vuelven más disjuntos.
25396577843.7769622802734375
También encontré un algoritmo de suma recursiva en awk estándar. Inicialmente, esto suma valores según los últimos 5 dígitos de NR, para formar 100.000 subtotales. Luego los suma, reduciendo el número de dígitos a 4, 3, 2, 1 y finalmente un total único. Por lo tanto, cada número recibe sólo 60 sumas. Ese resultado concuerda con los primeros 16 dígitos de los de alta precisión, lo cual es tan bueno como se podría esperar.
25396577843.756011962890625
Respuesta3
Verificarresumen de kahan, intenta realizar un seguimiento del error de redondeo y lo compensa. Imprescindible para sumas tan enormes.
Respuesta4
Con cvstool
y bc
:
$ csvtool -t '|' col 2 A | paste -sd + - | bc
149.5073562464567