
eu tenho cenário
onde estou tendo problemas porque a soma do UNIX de 8 a 9 escalas me dá uma soma incorreta, como consertar?
meu comando usado
awk -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
Este é o link para a pergunta anterior postada Por que existe uma diferença entre esses dois comandos de soma?
Qualquer maneira melhor de lidar com isso para que eu possa obter uma soma precisa
usando awk ou bc ou dc
Dados de demonstração
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
Responder1
Você não diz o tamanho do arquivo (ou seja, quantas linhas está adicionando). O download reivindicou 18,3 MB antes do site aparecer como “Perigoso” e “Alerta de Fraude”. Se o comprimento médio da linha for 18, isso representa um milhão de pontos flutuantes sendo adicionados e não sabemos a extensão dos valores. O total que você mostra na pergunta é de 13,2 dígitos, então o valor médio por linha fica em torno de 7 dígitos, com variabilidade desconhecida.
Se você continuar adicionando valores como 27,865326635297 a um total acumulado que está se aproximando de 13 dígitos inteiros, então apenas a parte 27,87 (arredondada) entrará no total porque 0,00532... está fora de 15 ou Faixa de resultados de 16 dígitos. Às vezes esses erros são anulados, às vezes não: aritmética de Monte Carlo.
Verifique a saída de awk --version. Se mencionar MPFR e MP, seu awk será compilado com matemática de precisão estendida. Você acabou de adicionar -M 113 ao seu comando awk. Esse é o comprimento da mantissa que proporciona aritmética real com precisão quádrupla - precisão de 33 dígitos.
www.gnu.org/software/gawk/manual/gawk.html#Arbitrary-Precision-Arithmetic
Responder2
Este é um método baseado naCCcomando (assumindo que este tenha precisão adequada compilada). Ele veste a segunda coluna com comandos dc e funciona com precisão de 60 dígitos (200 bits).
Isso é executado nas 10 linhas de dados fornecidas anteriormente, além de alguns valores extremos. Ele mostra somas intermediárias: para removê-las, remova o 'p' logo antes do \n onde o 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}"
}
Esclarecimento sobre os comandos dc emitidos (que estão em notação polonesa reversa):
'60 k' define a precisão aritmética e '0' inicializa o total.
'+' soma o valor de $2 ao total. 'p' imprime o total acumulado para ilustração.
'p q' imprime o total final e sai.
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--)
Agora temos quatro técnicas testadas (em relação ao seu arquivo de teste de 722.277 linhas), com classificações de precisão.
Usando gawk com precisão de 200 bits e dc com precisão de 60 dígitos, ambos concordam com o mesmo total de 33 dígitos, o que suspeito ser exato.
25396577843.7560139069641121618832
Usar o gawk na precisão padrão do IEEE (deve ter 15 ou 16 dígitos) concorda apenas com os primeiros 12 desses dígitos. Presumo que um milhão de adições corroam a precisão à medida que os expoentes se tornam mais disjuntos.
25396577843.7769622802734375
Também encontrei um algoritmo de adição recursivo no awk padrão. Isso inicialmente soma valores de acordo com os 5 últimos dígitos do NR, para perfazer 100.000 subtotais. Em seguida, totaliza-os, reduzindo o número de dígitos para 4, 3, 2, 1 e, finalmente, um único total. Cada número, portanto, recebe apenas 60 adições. Esse resultado está de acordo com os primeiros 16 dígitos dos de alta precisão, o que é tão bom quanto se poderia esperar.
25396577843.756011962890625
Responder3
ConfiraSoma de Kahan, ele tenta acompanhar o erro de arredondamento e compensa. Uma obrigação para somas tão grandes.
Responder4
Com cvstool
e bc
:
$ csvtool -t '|' col 2 A | paste -sd + - | bc
149.5073562464567