2014-03-27 2 views
2

아래 계산식으로 독립 실행 형 Enterprise COBOL 프로그램을 실행하고 있습니다. 여러 작업을 수행하는 COMPUTE가 있고 전체 계산이 분할되어 있습니다. 그러나 두 경우 모두 결과가 다릅니다 (마지막 4 자리 숫자).COBOL COMPUTE 계산

계산기를 사용하여 수동으로 계산 한 결과가 분할 된 COMPUTE 문과 일치합니다. 중간 결과에서 전체 답을 사용하고 최종 답안의 15 자리 만 사용하고 모든 중간 단계에서 반올림하지 않고 15 자리 만 사용하여 계산을 시도했습니다. 그러나 이러한 결과 중 어느 것도 COMPUTE 결과와 결합되지 않습니다.

왜 그런 차이가 있는지 이해할 수있는 사람이 있습니까? 지난 컴퓨팅의

 05 WS-A    PIC S9(3)V9(15) COMP. 
     05 WS-B    PIC S9(3)V9(15) COMP. 
     05 WS-C    PIC S9(3)V9(15) COMP. 
     05 WS-D    PIC S9(3)V9(15) COMP. 
     05 WS-E    PIC S9(3)V9(15) COMP. 
     05 WS-RES   PIC S9(3)V9(15) COMP. 
     05 RES-DISP   PIC -9(2).9(16). 

     MOVE 3.56784    TO WS-A. 
     MOVE 1.3243284234   TO WS-B. 
     MOVE .231433897121334834 TO WS-C. 
     MOVE 9.3243243213   TO WS-D. 
     MOVE 7.0     TO WS-E. 

     COMPUTE WS-RES = WS-A/WS-B. 
     MOVE WS-RES TO RES-DISP. 
     COMPUTE WS-RES = WS-RES/WS-C. 
     MOVE WS-RES TO RES-DISP. 
     COMPUTE WS-RES = WS-RES/(WS-D + WS-E). 
     MOVE WS-RES TO RES-DISP. 
     COMPUTE WS-RES = WS-RES * (WS-C - WS-A) 
     MOVE WS-RES TO RES-DISP. 
     COMPUTE WS-RES = WS-RES + WS-E ** WS-B 
     MOVE WS-RES TO RES-DISP. 
     COMPUTE WS-RES = WS-RES + WS-D. 
     MOVE WS-RES TO RES-DISP. 

결과 = 결합 컴퓨팅의 20.1030727225138740

 COMPUTE WS-RES = WS-A/WS-B/WS-C/
       (WS-D + WS-E) * (WS-C - WS-A) + 
       WS-E ** WS-B + WS-D. 
     MOVE WS-RES TO RES-DISP. 

결과 = 20.1030727225138680

+0

답변을 업데이트했습니다.보고있는 실제 문제라고 생각되는 지수화가있는 미묘한 점이 있습니다. 당신이 가지고있는 가치와 계산으로, 나는 당신이 가지고있는 것을 넘어선 주문 문제를 생각하지 않습니다. 왜 진단 메시지가 없는지 궁금 해서요. 내가 찾은 것 같아요. –

+0

이 특별한 상황은 어셈블리 목록 (목록)이 도움이 될 수있는 때입니다. 컴파일러가 생성하는 코드를 이해하면 결과를 이해하는 데 도움이됩니다. 최적화 또한 상황을 왜곡 할 수 있지만 C 및 PL/I와 동일한 코드 생성기를 사용하므로이 문제는 Enterprise COBOL 5.1에서 더 많은 문제가 될 것이라고 생각합니다. "재미"에 대해서는 원래 코드를 가져 와서 생성 된 코드를 비교합니다.Bill은 아래에서 이미 좋은 대답을 가지고 있으며 여기에 표시된 모든 코드 (원본 및 솔루션)와 생성 된 코드를 비교하면 컴파일러가 작동하는 방식을 더 잘 이해할 수 있습니다. – zarchasmpgmr

답변

3

느린, 나도 알아,하지만 난 당신이 모든 것을 정의한 이유에있어 생각 소숫점 15 자리. 그렇지 않으면 작동하지 않을 수 있습니다.

아래 링크의 질문 (물론 대답은 물론)을 읽어보십시오. 출력에 필요한 정밀도로 모든 필드를 지정할 필요는 없습니다.

COMPUTE을 재정렬하십시오. 주 COMPUTE 외부의 지수. 먼저 곱하십시오. 그런 다음 나누십시오. 모든 덧셈/뺄셈은 자연스럽게 맞습니다. 괄호를 사용하여 사람이 COMPUTE를 읽는 방법을 정확하게 지정하십시오 (컴파일러는 상관하지 않으며, 말한대로 할 수 있지만 때때로 사람들은 자신이 말하는 것을 모릅니다).

이렇게하면 정확하게 소수점 이하 15 자리가있는 모든 입력란에서 COMPUTE와 같은 대답을 얻을 수 있습니다.

이렇게하지 않으면 COMPUTE (및 복사 할 때 다른 사람)가 항상 깨지기 쉽고 변경하면 오류가 발생하기 쉽습니다.

계산기에 넣을 값을 볼 수 있도록 COMPUTE를 작은 것으로 분해하는 것이 좋습니다. 필드를 올바른 크기로 만들 때 똑같은 작업을 수행 할 수 있습니다.

여러 가지 업데이트로 인해 지저분 해지기 때문에 완전히 다시 작성해야합니다.

확인되었습니다. 차이점은 COMPUTE 내에서 비 ​​정수형 지수를 계산하기 때문입니다. 수동으로 말한 것처럼 COMPUTE (모든 중간 필드)의 모든 것을 소수점 이하 자릿수보다 큰 부동 소수점 숫자로 변환합니다. PICture 절에 지정된 15 개

곱셈으로 인해 36 자리 숫자를 갖지만 30 (ARITH (COMPAT)) 또는 31 (ARITH (EXTEND)) 만 가질 수있는 진단 메시지가 나타납니다. 상위 데이터가이 부분을 통해 잘리는 경우 런타임 메시지가 표시됩니다.

참고. ARITH (COMPAT) 15는 정밀도가 손실되지 않는 최대 유효 자릿수입니다 (64 비트 부동 소수점). ARITH (EXTEND)는 정밀도를 보장하지만 처리 (128 비트 부동 소수점)에 오버 헤드가 있습니다.

맨 위로 이전 ...

자세한 내용은 여기를 참조하십시오. 18 자리 숫자를 사용하고 있으며 컴파일 옵션으로 ARITH (EXTEND)를 사용하지 않았으며 큰 COMPUTE에 대해 생성 된 진단 메시지를 언급하지 않았습니다. 어느 것이 흥미 롭습니다.

COBOL에서 지수화를 많이 수행하지 않았고 정수로만 계산했습니다. 그래서 나는 매뉴얼을 보았다. 분수의 지수가 있기 때문에 큰 COMPUTE에있는은 모두 부동 소수점으로 처리됩니다. 그건 중요하지 않지만, 당신의 정의에있는 15 개의 십진수보다 더 큰 정확도로 일이 진행되고 있다는 것을 의미합니다. 귀하의 작은 COMPUTE에서는 이것이 일어나지 않습니다.

큰 COMPUTE에서 지수화를 취하여 따로 계산하고 그 결과를 큰 COMPUTE (지수를 대체하는 간단한 추가)에 넣는 것이 좋습니다. 나는 그 단계에서 컴파일러가 결과의 유효 자릿수에 대해 신음하기 시작할 것이라고 생각한다. 만약 그렇다면 실제로 중요한 숫자를 잃어 버리면 런타임 메시지를 받게됩니다.

당신이해야 :

  1. (데이터에 필요한 최대 크기로 각 필드를하지 정의 큰 COMPUTE 밖으로 지수를 타고 지수
  2. 별도의 COMPUTE의 결과로 교체
  3. 이 COMP-3 COMP에서에
  4. (아마) 변화 만이 스스로를 테스트) 모두를위한 가능한 최대
  5. Parenthesise 모든 인간의 독자가 컴파일러는
  6. ,691에서 일을 할 것입니다 순서를 알 수 있도록
  7. COMPUTE에서 가능한 절단에 대한 경고가 계속 표시되면 ARITH (EXTEND) 컴파일러 옵션을 살펴보고 수정 사항으로 넣지 말고 필요한 경우에만 사용하고 해당 프로그램에 대한 사용을 문서화하십시오

나는 나중에 이것을 확인하려고 노력할 것이지만, 나는 그것을 소트 할 것이라고 생각한다.

다음은 시작이었고, 여전히, 일반적으로 특정 질문 (문제 만 지수에 대한 강제 대 모두에 강제로 더 높은 부동 소수점 정밀도 인)에 대한 비록 직접 관련이없는 적용

귀하 작은 COMPUTE 문제는 대형 COMPUTE의 요소와 동일한 순서로 해당 명령을 실행하지 않는다는 것입니다.

()은 즐거움이 없거나 함께 그룹화하기 위해 계산에 우선 순위를 설정합니다.

그 밖의 우선 순위는 무엇입니까? 사용 된 연산자. 우선 순위는 무엇입니까? 글쎄, 당신이 그것을 수동으로 보거나, 암기하거나, 잊어 버릴 때마다 매번 익숙해 져야한다. Mmmmm .... 좋은 제안이 아닙니다.

또한 다른 사람들이 귀하가 작성하거나 변경하는 프로그램을 작업하게됩니다. 그리고 그들은 컴퓨터가 어떻게 작동 하는지를 "알 수"있습니다. 나는 그들이하지 않는다는 것을 의미하지만 생각하지는 않습니다. 그래서 그것을 보지 않을 것입니다. Doubly-not-good suggestion.

그래서 ....

사용 () 당신이 일을하고자하는 순서를 정의합니다.

중요한 점을 잊어 버릴 수도 있습니다. 이 문서를 보시고, AS/400: Using COMPUTE function, inconsistent results with different field definition, Enterprise COBOL 매뉴얼의 참조 된 부분을 읽고 이해하십시오.

본 사이트에 링크 된 질문의 요약으로, 중간 결과가 유효 자릿수를 잃지 않도록 first와 divide last를 요약하십시오. 의도적으로 숫자를 잃고 싶지 않은 경우, 해당 COMPUTE가 개별적으로 중요성을 잃고 코드에 주석을 달아 아무도 "수정"하지 않도록하십시오.

또한 메인 프레임에서 소수점 이하 자릿수 필드에 COMP/COMP-4/BINARY/COMP-5를 사용하는 것은 드문 경우입니다. COMPUTE에 만족하면 프로그램을 복사하고 필드 정의를 COMP-3/PACKED-DECIMAL로 변경하십시오. 각 프로그램의 카운터에 루프를 넣고 CPU 사용량에 큰 차이가 있는지 확인하십시오.

1

나는 컴파일, 복사 사소한 변경의 부부와 함께 프로그램을 실행 :

  • 추가 된 새로운 변수 WS-EXP PIC S9(3)V9(15) COMP
  • 추가 된 새로운 계산이 같은 일을 컴파일러 절단 경고를 피하기 위해 PIC -9(3).9(15)RES-DISP을 선언 Bill Woodger는 지수 계산을 다음과 같이 별도 계산으로 나누어 제안했습니다.
COMPUTE WS-EXP = WS-E ** WS-B 
    COMPUTE WS-RES = WS-A/WS-B/WS-C/ 
    (WS-D + WS-E) * (WS-C - WS-A) + 
    WS-EXP + WS-D. 

이 프로그램에서 발행 된 유일한 컴파일러 경고는 위의 두 번째 COMPUTE 문에 대한 것입니다. 메시지였다 020.103072722513874 :

IGYPG3113-W Truncation of high-order digit positions may occur due to intermediate results exceeding 30 digits 

위의 COMPUTE의 결과는 정확히 조각 계산과 동일합니다. 올인원 COMPUTE 문으로 인해 컴파일러 경고가 발생하지 않았습니다. 그러나 내부 지수에 따라 보다 정밀한 중간 결과가 산출되어 (더 적은 반올림) 약간 다른 결과 (020.103072722513868)가 생성되었습니다.

여기 또 다른 흥미로운 관찰. ARITH (COMPAT) 사용하기 ARITH (EXTEND) I 을 사용하여 단편적인 계산을 위해 020.103072722513877을 얻고 올인원 COMPUTE를 020103072722513874 (정확히 단편적인 계산과 동일하게 사용함 ARITH (COMPAT)로 컴파일 할 때).

모두 복잡한 계산을 할 때 숫자 정밀도, 반올림 및 잘림 규칙을 실제로 연구해야한다는 것을 보여줍니다. 이것은 이며 특히 프로그래머가 사용할 수있는 다른 숫자 데이터 유형의 수 때문에 COBOL의 경우에 해당됩니다.