[Cobol] COBOL и $2 020 202,02 (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
05-Ноя-2020 20:32

В прошлые годы, даже в последние год-два мне иногда попадались новости, что кому-то пришёл счёт или чек на смешную сумму 2 020 202 доллара… и 02 цента.
Если вы такое увидите, то (почти наверняка) это ошибка программирования на COBOL. Большинство программистов COBOL совершают эту глупую ошибку, и я не исключение.
Проблема вызвана тем, как именно мы обычно инициализируем запись. Возьмём такую маленькую программу:
identification division.
       program-id.
           mistake.
       data division.
       working-storage section.
      * *** Input record, typically maintained on disk/tape somewhere.
       01  dr-datarec.
           03  dr-name                 pic x(20).
           03  dr-amount               pic s9(7)v99, comp-3.
      * *** print record, sent to a line printer.
       01  dt-detail.
           03  dt-name                 pic x(20).
           03  filler                  pic x.
           03  dt-amount               pic z,zzz,zz9.99.
       procedure division.
           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.
           move spaces                 to dt-detail.
           move dr-name                to dt-name.
           move dr-amount              to dt-amount.
           display dt-detail.
           stop run.

В этой программе входная запись dr-datarec. Обычно она идёт откуда-то с диска, но для этого простого теста создаётся вручную.
Как только получена входная запись, выполняются вычисления, а затем запись выводится с помощью dt-detail.
Проблема в том, как создаётся запись dr-datarec. Обратите внимание, как перемещаются пробелы для её инициализации. Это был типичный метод инициализации записи.
Таким образом, пробелы есть во всех полях PIC X. Но! Все поля COMP-3 также инициализируются, только не до нуля. Программист должен быть уверен, что для всех полей COMP-3 создаются допустимые значения. В тестовой программе это делается правильно:
move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.

В поле dr-amount явно есть 100. После запуска получается:
./mistake
test                       100.00

Что делать, если допущена ошибка кодирования и запись dr-amount не инициализирована должным образом?
Там всё ещё есть пробелы ASCII. Это шестнадцатеричное значение 20 или двоичное 0010 0000.
COMP-3 хранит цифры в виде четырёхбитных «нибблов», поэтому один пробел отображается как 20. Если у вас 9 цифр, как у dr-amount, то для этого требуется 10 нибблов памяти (9 нибблов для цифр и один для знака) или 5 байт.
Перемещение пробелов в dr-datarec приведёт к тому, что в это поле сохранится 5 пробелов или шестнадцатеричное значение 2020202020. Если попытаться использовать неинициализированную переменную, это интерпретируется как 2 020 202,02.
Если закомментировать инициализацию dr-amount, то можно принудительно вызвать эту ошибку:
move spaces                 to dr-datarec.
           move "test"                 to dr-name.
     *     move 100                    to dr-amount.

Теперь при запуске программы:
./mistake
test                 2,020,202.02

Чтобы исправить эту проблему, COBOL 85 ввёл глагол INITIALIZE. Вместо перемещения пробелов в запись вы её инициализируете, а она переместит пробелы в буквенно-цифровые поля, а нули — в числовые:
*    move spaces                 to dr-datarec.
           initialize dt-detail.
           move "test"                 to dr-name.
      *    move 100                    to dr-amount.

Результат выполнения:
./mistake
test                         0.00

Так что в следующий раз, когда увидите бедную вдову, которой пришёл счёт за коммунальные услуги $2 020 202,02, вы будете точно знать, что произошло!
===========
Источник:
habr.com
===========

===========
Автор оригинала: Big Dan the Blogging Man
===========
Похожие новости: Теги для поиска: #_cobol, #_cobol, #_programmirovanie (программирование), #_oshibka (ошибка), #_cobol
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 18:39
Часовой пояс: UTC + 5