장면이 있어요
8~9 범위의 UNIX 합계에서 잘못된 합계가 제공되기 때문에 문제가 있습니다. 어떻게 해결합니까?
내가 사용한 명령
awk -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
이전 질문에 대한 링크는 다음과 같습니다. 이 두 sum 명령 사이에 차이점이 있는 이유는 무엇입니까?
정확한 금액을 얻을 수 있도록 처리하는 더 좋은 방법이 있습니까?
awk, bc 또는 dc를 사용하세요.
데모 데이터
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
답변1
파일 크기(즉, 추가하려는 줄 수)를 말하지 않았습니다. 사이트가 "위험" 및 "사기 경고"로 표시되기 전의 다운로드 크기는 18.3MB였습니다. 평균 행 길이가 18이면 이는 백만 개의 부동 소수점이 추가된 것이며 값의 범위를 알 수 없습니다. 질문에 표시되는 총 숫자는 13.2비트이므로 행당 평균은 약 7비트이며 변동성은 알 수 없습니다.
13자리 정수에 가까운 누계에 27.865326635297과 같은 값을 계속 추가하면 .00532...가 15자리 또는 16자리 결과 범위를 벗어나기 때문에 27.87(반올림) 부분만 합계에 포함됩니다. 때로는 이러한 오류가 서로 상쇄되기도 하고 때로는 그렇지 않은 경우도 있습니다. 몬테 카를로 산술.
awk --version의 출력을 확인하세요. MPFR 및 MP가 언급되면 awk는 확장 정밀 수학으로 컴파일됩니다. awk 명령에 -M 113을 추가하기만 하면 됩니다. 이는 4배 정밀도의 실수 산술(33비트 정밀도)을 수행할 수 있는 가수의 길이입니다.
www.gnu.org/software/gawk/manual/gawk.html#임의-정밀-산술
답변2
이는 다음을 기반으로 합니다.직류명령(컴파일이 충분히 정확하다고 가정). dc 명령을 사용하여 두 번째 열을 수정하고 60비트(200비트) 정밀도로 작동합니다.
이는 이전에 제공된 10개의 데이터 라인과 몇 가지 극단적인 데이터 라인에서 작동합니다. 중간 합계가 표시됩니다. 이를 제거하려면 awk가 $2를 방출하는 \n 앞에 있는 'p'를 제거하십시오.
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}"
}
실행된 dc 명령에 대한 설명(역폴란드 표기법):
"60 k"는 연산 정밀도를 설정하고, "0"은 총 개수를 초기화합니다.
'+'는 총액에 $2의 값을 더합니다. 'p'는 설명을 위해 누계를 인쇄합니다.
'p q'는 최종 합계를 인쇄하고 종료합니다.
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--)
이제 정확도 등급이 있는 4가지 테스트된 기술(722277 라인의 테스트 파일)이 있습니다.
200비트 정밀도의 gawk와 60비트 정밀도의 dc를 사용하면 둘 다 동일한 33비트 전체에 동의하는데 이것이 정확할지 의심스럽습니다.
25396577843.7560139069641121618832
표준 IEEE 정밀도(15 또는 16비트여야 함)에서 gawk를 사용하면 이러한 숫자의 처음 12자리에만 동의합니다. 나는 백만 개의 추가가 지수가 더 분리되기 때문에 정확도를 약화시킬 것이라고 가정합니다.
25396577843.7769622802734375
또한 표준 awk에서 재귀 추가 알고리즘을 찾았습니다. 이는 NR의 마지막 5자리를 기준으로 값을 추가하여 소계 100,000을 형성하는 것으로 시작됩니다. 그런 다음 이 숫자를 더해 자릿수를 4, 3, 2, 1로 줄이면 최종적으로 합계가 구해집니다. 따라서 번호당 60개만 추가할 수 있습니다. 이 결과는 예상대로 고정밀 결과의 처음 16비트와 일치합니다.
25396577843.756011962890625
답변3
확인하다카한화, 반올림 오류를 추적하고 이를 보상하려고 시도합니다. 그렇게 큰 돈이 필요합니다.
답변4
그리고 :cvstool
bc
$ csvtool -t '|' col 2 A | paste -sd + - | bc
149.5073562464567