USAGE dan Penyimpanan

USAGE DISPLAY, COMP biner, dan COMP-3 desimal paket, termasuk konsekuensi pemilihannya.

Daftar isi

Klausa USAGE menentukan cara sebuah item data disimpan di dalam memori, dan pilihan itu memengaruhi ukuran, keterbacaan berkas, serta cara item diperlakukan pada aritmetika. Topik ini membahas tiga USAGE yang paling sering digunakan, yaitu DISPLAY dengan satu digit per byte, COMP dengan penyimpanan biner, dan COMP-3 dengan desimal paket, lengkap dengan jebakan penyalinan grup yang melintasi USAGE yang berbeda.

USAGE DISPLAY satu digit per byte#

Tanpa klausa USAGE, item data menggunakan USAGE DISPLAY, yaitu penyimpanan satu byte per posisi picture dengan setiap digit tersimpan sebagai karakter. Ukurannya mudah dihitung, yaitu jumlah posisi picture sama dengan jumlah byte, dan kebenarannya dapat dibuktikan dengan FUNCTION LENGTH yang mengembalikan ukuran item dalam byte. Simbol V dan tanda yang tersimpan dalam digit tidak menambah byte, sedangkan klausa SIGN TRAILING SEPARATE menambah satu byte untuk karakter tandanya.

cobol ukuran-display.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UKURAN-DISPLAY.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 KODE-PRODUK  PIC 9(5).
       01 NAMA-BARANG  PIC X(10).
       01 HARGA        PIC S9(7)V99.
       01 HARGA-STS    PIC S9(7)V99 SIGN TRAILING SEPARATE.
       01 PANJANG      PIC Z9.
       PROCEDURE DIVISION.
           COMPUTE PANJANG = FUNCTION LENGTH(KODE-PRODUK)
           DISPLAY "PIC 9(5)          : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(NAMA-BARANG)
           DISPLAY "PIC X(10)         : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(HARGA)
           DISPLAY "PIC S9(7)V99      : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(HARGA-STS)
           DISPLAY "PIC S9(7)V99 +STS : " PANJANG " byte"
           STOP RUN.
text Keluaran
PIC 9(5)          :  5 byte
PIC X(10)         : 10 byte
PIC S9(7)V99      :  9 byte
PIC S9(7)V99 +STS : 10 byte

Hasil pengukuran cocok dengan aturan satu byte per posisi. Field PIC S9(7)V99 berukuran 9 byte karena memuat tujuh digit dan dua digit desimal, sedangkan simbol V hanya menandai posisi logis titik desimal dan tidak menempati byte. Versi dengan SIGN TRAILING SEPARATE menjadi 10 byte karena karakter tandanya disimpan sebagai satu karakter terpisah di ujung field.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./ukuran-display.

bash
# kompilasi program menjadi eksekutabel
cobc -x ukuran-display.cbl

COMP biner dan COMP-3 desimal paket#

USAGE COMP menyimpan bilangan sebagai biner utuh, dan GnuCOBOL menempatkan 1 sampai 4 digit pada 2 byte, 5 sampai 9 digit pada 4 byte, serta 10 sampai 18 digit pada 8 byte. USAGE COMP-3, yang juga disebut desimal paket atau packed decimal, menyimpan dua digit dalam satu byte ditambah satu nibel (nibble) tanda di ujung, sehingga ukurannya adalah ⌊d/2⌋+1 \lfloor d/2 \rfloor + 1 byte untuk d d digit. Nilai 123.45 dalam PIC 9(5)V99 COMP-3 tersimpan sebagai empat byte yang memuat digit 0012345 dan nibel tanda F. COMP, COMP-4, dan COMP-5 sama-sama biner pada GnuCOBOL, sedangkan COMP-1 dan COMP-2 adalah bilangan pecahan floating point 4 dan 8 byte yang tidak tepat untuk nilai uang karena pecahan desimal tidak pernah eksak dalam biner.

cobol ukuran-usage.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UKURAN-USAGE.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 BIN-KECIL    PIC 9(4)  COMP VALUE 45.
       01 BIN-SEDANG   PIC 9(7)  COMP VALUE 1234567.
       01 BIN-BESAR    PIC 9(12) COMP VALUE 123456789012.
       01 PAKET-KECIL  PIC 9(3)     COMP-3 VALUE 451.
       01 PAKET-BESAR  PIC S9(5)V99 COMP-3 VALUE 123.45.
       01 PANJANG      PIC Z9.
       PROCEDURE DIVISION.
           COMPUTE PANJANG = FUNCTION LENGTH(BIN-KECIL)
           DISPLAY "PIC 9(4) COMP    : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(BIN-SEDANG)
           DISPLAY "PIC 9(7) COMP    : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(BIN-BESAR)
           DISPLAY "PIC 9(12) COMP   : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(PAKET-KECIL)
           DISPLAY "PIC 9(3) COMP-3  : " PANJANG " byte"
           COMPUTE PANJANG = FUNCTION LENGTH(PAKET-BESAR)
           DISPLAY "PIC S9(5)V99 C-3 : " PANJANG " byte"
           DISPLAY BIN-KECIL " " BIN-SEDANG " " BIN-BESAR
           DISPLAY PAKET-KECIL " " PAKET-BESAR
           STOP RUN.
text Keluaran
PIC 9(4) COMP    :  2 byte
PIC 9(7) COMP    :  4 byte
PIC 9(12) COMP   :  8 byte
PIC 9(3) COMP-3  :  2 byte
PIC S9(5)V99 C-3 :  4 byte
0045 1234567 123456789012
451 +00123.45

Dua baris terakhir menunjukkan bahwa DISPLAY tetap merender nilai COMP dan COMP-3 sebagai desimal yang terbaca, sehingga penyimpanan biner tidak mengubah cara nilainya ditampilkan. Tanda plus pada +00123.45 berasal dari field COMP-3 bertanda yang tampil dengan tandanya. Tabel berikut merangkum ukuran yang terverifikasi melalui pengukuran di atas dan juga tercantum pada dokumentasi GnuCOBOL maupun IBM.

PictureUSAGEDigitUkuran terukur
9(4)COMP42 byte
9(7)COMP74 byte
9(12)COMP128 byte
9(3)COMP-332 byte
S9(5)V99COMP-374 byte

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./ukuran-usage.

bash
# kompilasi program menjadi eksekutabel
cobc -x ukuran-usage.cbl

Jebakan MOVE grup antar USAGE#

MOVE grup menyalin byte tanpa konversi, dan salinan itu menjadi kacau ketika grup asal berisi item COMP-3 sedangkan grup tujuan berisi item DISPLAY. Program berikut menyalin grup berisi item COMP-3 ke grup berisi item DISPLAY, lalu memeriksa byte hasil salinan satu per satu dengan FUNCTION ORD yang mengembalikan nomor karakter pada urutan kolasi.

cobol grup-usage.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. GRUP-USAGE.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 GRUP-PAKET.
          05 TOTAL-PESERTA  PIC 9(5)V99 COMP-3 VALUE 123.45.
       01 GRUP-CETAK.
          05 TOTAL-TAMPIL   PIC 9(5)V99.
       01 INDEKS         PIC 9.
       01 UKUR-BYTE     PIC ZZZ9.
       PROCEDURE DIVISION.
           MOVE GRUP-PAKET TO GRUP-CETAK
           PERFORM VARYING INDEKS FROM 1 BY 1 UNTIL INDEKS > 7
            COMPUTE UKUR-BYTE = FUNCTION ORD(TOTAL-TAMPIL(INDEKS:1))
            DISPLAY "byte " INDEKS ": " UKUR-BYTE
           END-PERFORM
           MOVE TOTAL-PESERTA TO TOTAL-TAMPIL
           DISPLAY "Salinan elementer : [" TOTAL-TAMPIL "]"
           STOP RUN.
text Keluaran
byte 1:    1
byte 2:   19
byte 3:   53
byte 4:   96
byte 5:   33
byte 6:   33
byte 7:   33
Salinan elementer : [00123.45]

Nomor karakter pada keluaran dikurangi satu menghasilkan kode byte sesungguhnya, sehingga empat byte pertama terbaca sebagai 0, 18, 52, dan 95. Kode 52 dan 95 adalah karakter 4 dan _, sedangkan kode 0 dan 18 adalah karakter kontrol yang tidak tercetak di terminal. Byte paket 123.45 memang tersalin apa adanya, sehingga field PIC 9(5)V99 yang menerima byte bukan digit menampilkan isi yang kacau. Tiga byte terakhir bernilai spasi karena grup tujuan lebih besar dan MOVE grup mengisi sisanya dengan spasi.

Baris terakhir keluaran memperlihatkan cara penyalinan yang benar. MOVE elementer dari TOTAL-PESERTA ke TOTAL-TAMPIL memicu konversi karena keduanya item elementer bertipe numeric, sehingga 123.45 tampil benar sebagai 00123.45. Alternatif lain adalah memindahkan nilai ke field hasil edit agar tampilannya langsung terformat.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./grup-usage.

bash
# kompilasi program menjadi eksekutabel
cobc -x grup-usage.cbl

Konsekuensi pemilihan USAGE#

Ketiga USAGE menghasilkan aritmetika desimal yang eksak karena semuanya bekerja pada bilangan tetap (fixed point), berbeda dari floating point yang menyimpan pecahan secara hampiran. Pembedanya ada pada ukuran penyimpanan, keterbacaan data, dan kecepatan pemrosesan, sebagaimana dirangkum tabel berikut untuk field PIC 9(7).

AspekDISPLAYCOMPCOMP-3
Ukuran 7 digit7 byte4 byte4 byte
Terbaca langsung sebagai teksyatidaktidak
Aritmetika desimal eksakyayaya

USAGE DISPLAY menghasilkan berkas terbesar tetapi isinya dapat dibaca dengan editor teks, sehingga cocok untuk berkas laporan dan data yang diperiksa manusia. COMP dan COMP-3 memangkas ukuran berkas serta mengurangi beban konversi saat aritmetika berat, dan COMP-3 menjadi pilihan lazim untuk nilai uang karena penataan digitnya persis mengikuti notasi desimal. Konsekuensi terpentingnya terletak pada berkas, karena record yang ditulis dengan suatu USAGE harus dibaca kembali dengan definisi yang sama persis, termasuk USAGE-nya.

Kesalahan umum#

  • Menyalin grup yang berisi item COMP-3 atau COMP ke grup berisi item DISPLAY. Byte paket dan biner tersalin mentah sehingga field tujuan berisi data tak sah, sebagaimana ditunjukkan program grup-usage.cbl. Salin per item elementer agar konversi terjadi.
  • Menggunakan COMP-1 atau COMP-2 untuk nilai uang. Keduanya adalah floating point yang tidak menyimpan pecahan desimal secara eksak, sehingga penjumlahan berulang menimbulkan selisih pembulatan. Gunakan COMP-3 atau COMP beserta simbol V untuk nilai uang.
  • Membaca ulang berkas dengan definisi yang USAGE-nya berbeda dari saat ditulis. Byte yang tersimpan tidak berubah, tetapi pembacaannya kacau seperti pada salinan grup antar USAGE. Definisi record pada program penulis dan pembaca berkas harus identik.

Ringkasan#

  • USAGE DISPLAY menyimpan satu digit per byte, simbol V tidak menambah byte, dan SIGN TRAILING SEPARATE menambah satu byte untuk tanda.
  • COMP menyimpan biner dengan ukuran 2, 4, dan 8 byte untuk 1 sampai 4, 5 sampai 9, serta 10 sampai 18 digit, sedangkan COMP-3 menyimpan dua digit per byte ditambah nibel tanda.
  • MOVE grup menyalin byte tanpa konversi, sehingga salinan antar USAGE menghasilkan data tak sah dan hanya MOVE elementer yang mengonversi dengan benar.
  • Aritmetika tetap eksak pada ketiga USAGE, sedangkan pembedanya adalah ukuran berkas, keterbacaan, dan kecepatan pemrosesan.

Referensi#