부동 값을 합산하는 더 좋은 방법은 무엇입니까? 유닉스 합계는 최대 8~9까지의 값으로 잘못된 합계를 제공합니다.

부동 값을 합산하는 더 좋은 방법은 무엇입니까? 유닉스 합계는 최대 8~9까지의 값으로 잘못된 합계를 제공합니다.

나한테는 시나리오가 있어

UNIX 합산이 8~9개 스케일로 인해 잘못된 합산이 발생하기 때문에 문제가 있는 곳은 어디입니까? 어떻게 해결해야 합니까?

내가 사용한 명령

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자리 밖에 있기 때문에 27.87(반올림된) 부분만 합계에 포함됩니다. 16자리 결과 범위. 때로는 이러한 오류가 취소되기도 하고 때로는 취소되지 않는 경우도 있습니다. 몬테카를로 산술.

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

와 :cvstoolbc

$ csvtool -t '|' col 2 A | paste -sd + - | bc
149.5073562464567

관련 정보