【COBOL 書き1-12-12】中央値の処理をコードにする〜わくコ誕生

🧩今日の学び
・偶数と奇数で中央値処理全体を分けず、REMAINDERによって中央として使うLOW-POSHIGH-POSだけを切り替えれば処理を共通化できる。
・奇数件では2で割った商に1を加えた中央位置をLOW-POSHIGH-POSの両方に設定し、同じ値を2回選んで平均することで偶数件と同じ計算へ統一できる。
・違いを位置決定部分だけへ押し込み、データ取得と平均計算を共通化することで、分岐を増やさず短く保守しやすいコードにできる。

係長)もうここまでいったんだ、あとは分かるだろ?

なるお)合点承知!おまかせARRAY!

係)ARRAYのことなんか知らんだろ。

な)きぃ!

係長だって知らないことあるでしょ!

現在人類が観測できている一番高い山は?

はい!小惑星ベスタのレアシルヴィアの中央丘です!どうですかこれ!

係)丘って言ってんじゃねーか。

な)きぃ!そこじゃないから!

係)うるさいから、さっさと仕上げろって。

な)なんで冷静に丘にツッコんでんのよ、「そうそう25000メートルな!」ってノッてこいっての!

……… で、なんだって?

あ、全体コードか。もう忘れたってのまったく

まずは件数を数える処理をそのまま使う

な)まずはカウント部分は変わらないんだから、こうでしょー。

📝 COBOL カウント部分
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT IS NUMERIC
                           AND OUTPUT-AMOUNT > 0
                           ADD 1 TO COUNT-LOOPING
                       END-IF
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.

OUTPUT-AMOUNTを数字判定して、0より大きかったら、カウント1追加して次のルーピングへ。最後まで行ったら、EOF-FLAGをYにしてルーピングへ

ってところは変わらないわけで…

余りを使ってLOW-POSとHIGH-POSを決める

な)で、割り算して、番目が偶数か奇数かの場合分けになると

っこれももう出してるわけだからして…

DIVIDE BY GIVING REMAINDだから、COUNT-LOOPING2で割って、割り切れても割り切れなくても、偶数・奇数のどっちでも2で割った商がLOW-POSに入るし、HIGH-POSは余りがでなかったら、偶数になるので平均となって、LOW-POSの次の整数もいるから、LOW-POS+1になるって話よ。

HIGH-POSは余りがでたら、LOW-POS = HIGH-POSのってことでいいわよね。うふふ

だからこう!

📝 COBOL 偶数か奇数か判別
           DIVIDE COUNT-LOOPING BY 2 GIVING LOW-POS
               REMAINDER REMAIND.
           IF REMAIND = 0
               COMPUTE HIGH-POS = LOW-POS + 1
           ELSE
               COMPUTE HIGH-POS = LOW-POS
           END-IF.

人類のワクワクがとまらないコード、「わくコ」だね。

2回目のループで対応する金額を取り出す

んで、次。

ついに地球がなぜ生まれたかの謎が解かれるわけで、

ソートファイルの中でカウントの順番に対応する価格を抽出しますよってところからだから、EOF-FLAGYになるまでまたルーピング…と、今YにってるからNMOVEで入れとかないとルーピングしないよねってことで、

まずはこうと、MOVE "N" TO EOF-FLAG

その後NOT AT ENDで、OUTPUT-AMOUTNUMERICして、0より大きかったらCOUNTを1増やす

これをLOW-POSと比較して同一だったら、その番目の額を引っ張ってきてLOW-VALに入れると。

もう一丁、HIGH-POSと比較してREAD-COUNTと同一だったら、その番目の額をHIGH-VALに入れると。それで終わり、ルーピングまで終了

📝 COBOL 対応額突き詰め部
           OPEN INPUT OUTPUT-FILE.
           MOVE "N" TO EOF-FLAG.
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT IS NUMERIC
                           AND OUTPUT-AMOUNT > 0
                           ADD 1 TO READ-COUNT
                           IF READ-COUNT = LOW-POS
                               MOVE OUTPUT-AMOUNT TO LOW-VAL
                           END-IF
                           IF READ-COUNT = HIGH-POS
                               MOVE OUTPUT-AMOUNT TO HIGH-VAL
                           END-IF
                       END-IF
               END-READ
           END-PERFORM.

最後に2つの値を平均して中央値を出す

そんであとは表示のための計算なので、

LOWHIGHVALを足して2で割れば感性っとあとは体裁を整えて…

こうりゃんす!

📝 COBOL 出力用計算・表示部
           COMPUTE MEDIAN-VAL = (LOW-VAL + HIGH-VAL) / 2.
           DISPLAY "COUNT=" COUNT-LOOPING
                   " LOW-POS=" LOW-POS " HIGH-POS=" HIGH-POS.
           DISPLAY "MEDIAN IS " MEDIAN-VAL.

全体まとめて…こうりゃんす!

📝 COBOL PROCEDURE部
       PROCEDURE DIVISION.
           SORT SORT-FILE
               ON ASCENDING KEY SORT-AMOUNT
               USING INPUT-FILE
               GIVING OUTPUT-FILE.
           OPEN INPUT OUTPUT-FILE.

           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT IS NUMERIC
                           AND OUTPUT-AMOUNT > 0
                           ADD 1 TO COUNT-LOOPING
                       END-IF
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.

           DIVIDE COUNT-LOOPING BY 2 GIVING LOW-POS
               REMAINDER REMAIND.
           IF REMAIND = 0
               COMPUTE HIGH-POS = LOW-POS + 1
           ELSE
               COMPUTE HIGH-POS = LOW-POS
           END-IF.

           OPEN INPUT OUTPUT-FILE.
           MOVE "N" TO EOF-FLAG.
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT IS NUMERIC
                           AND OUTPUT-AMOUNT > 0
                           ADD 1 TO READ-COUNT
                           IF READ-COUNT = LOW-POS
                               MOVE OUTPUT-AMOUNT TO LOW-VAL
                           END-IF
                           IF READ-COUNT = HIGH-POS
                               MOVE OUTPUT-AMOUNT TO HIGH-VAL
                           END-IF
                       END-IF
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.

           COMPUTE MEDIAN-VAL = (LOW-VAL + HIGH-VAL) / 2.
           DISPLAY "COUNT=" COUNT-LOOPING
                   " LOW-POS=" LOW-POS " HIGH-POS=" HIGH-POS.
           DISPLAY "MEDIAN IS " MEDIAN-VAL.
           STOP RUN.

ってわけですね!これ「わくコ」でしょ!

おむすび

係)… ふーん。

な)なんなんすか、いっつも、不穏な空気だして!そんなに崖に立ちたいんすか!そんなに火曜日に出演したいんすか!?

係)何の話だよ!

ま、DATA DIVISION揃えたら出来上がるわけだから、そこまでいってみろ。

な)ほんとやな感じ醸し出すの得意ですよね…

もっと褒め称えて!崇めて!奉って!

係)お前を上に思ったことなんかないからな。

な)係長もあんま目上に思えないんすけど?

係)どういうことだよ!

(もう少し続く)

係長のワンポイント

偶数と奇数は「別々の中央値処理」を持つ必要はない。
本当は、中央として選ぶ2つの位置だけを変えれば、同じ計算で処理できる。
よくある誤解は、奇数なら1件、偶数なら2件と考えて処理そのものを分岐させることだ。
しかし奇数も「同じ中央値を2回選んで平均する」と考えれば、後半の計算は共通化できる。
その結果、分岐は“位置を決める部分”だけに絞れ、コード全体を短く保てる。
COBOLは処理を増やして対応する言語ではなく、違いを位置や条件へ押し込んで共通化する言語だ

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

CAPTCHA