2016-04-08 3 views
0

Код работает нормально, когда я выполняю вычисление x раз. однако множитель не меняется, когда я делаю это таким образом. Я новичок в COBOL, поэтому я не уверен, что я делаю неправильно. Я в основном хочу цикл while, который работает до тех пор, пока множитель не станет больше 0. Так как cobol не имеет рекурсии, я пытаюсь это сделать, он отлично работает на C, однако он дает мне проблемы с точки зрения цикла здесь.программа умножения больших чисел, выполняется до тех пор, пока цикл не будет работать в cobol

identification division. 
program-id. multiplication. 

data division. 

working-storage section. 
01 multiplier picture 9(36). 
01 multiplicand picture 9(36). 
01 answer picture 9(36). 

procedure division. 
begin. 
    display 'multiplier?'. 
    accept multiplier. 
    display 'multiplicand?'. 
    accept multiplicand. 
    perform calculation 
     with test after 
     until multiplier > 0. 
    display answer. 

calculation. 
    if ((function mod(multiplier, 2)) = 1) then 
     add multiplicand to answer 
    end-if. 
    divide 2 into multiplier. 
    multiply 2 by multiplicand. 
+0

До множителя> 0? Разве вы не имеете в виду, когда множитель> 0? – Mike

+0

да, извините, но. Должен ли я использовать пока? –

+2

Либо это, либо «до множителя <= 0». Прошло 30 лет с тех пор, как я использовал COBOL на старом мэйнфрейме IBM. – Mike

ответ

1

Похоже, что вы используете GnuCOBOL (или старую OpenCOBOL, GnuCOBOL это новое название для OpenCOBOL). Стандарт COBOL 2002 года (в настоящее время стандартом 2014 года) вводит рекурсию в COBOL (IS RECURSIVE по идентификатору PROGRAM-ID), а GnuCOBOL поддерживает рекурсию, и она довольно распространена среди других компиляторов COBOL.

Это в стороне, зачем использовать рекурсию для чего-то, когда есть не извилистая альтернатива?

У вас есть три актуальные проблемы, два из которых уже включены в комментарии к вашему вопросу.

UNTIL. Это означает, что «пока это условие не существует, продолжайте делать PERFORM». Он может быть расположен на «вершине» итерации (первое) или внизу (последнее). Когда условие истинно, PERFORM не будет выполняться. Независимо от того, выполняется ли PERFORM, когда условие изначально истинно, зависит от WITH TEST. С ИСПЫТАНИЕМ ДО (по умолчанию) означает, что PERFORM не будет выполняться вообще, если условие истинно, когда встречается PERFORM. WITH TEST AFTER задерживает тест до тех пор, пока не завершится первое выполнение кода (для встроенного PERFORM) или параграфа (ов)/SECTION.

множитель уже больше нуля, когда встречается PERFORM. Вы используете WITH TEST AFTER, поэтому вы получаете один снимок, чтобы изменить значение завершения. Код не делает ничего, чтобы убедиться, что множитель не больше нуля, поэтому абзац PERFORMed больше не будет введен, поскольку условие завершения является истинным.

Используйте EQUAL TO ZERO, выровняйте С ИСПЫТАНИЕМ ПОСЛЕ. множитель не может быть отрицательным, и он не имеет десятичной части. Когда один делится на два и результат сохраняется, этот результат будет равен нулю. Это обязательно и обязательно произойдет каждый раз в вашей программе. Это ваше условие завершения.

Вы определили ответ и используете его как цель добавления, но перед добавлением он не имеет гарантированного значения. Установите его в ноль (предложение VALUE или MOVE ZERO TO ... или INITIALIZE ...), прежде чем использовать его в качестве цели вычисления любого типа. Однако, не давайте ему начальное значение, если оно не нуждается в нем.

Если первый раз something используется как это:

ADD x TO something 

Тогда вы должны убедиться, что он имеет начальное значение. Если это так:

MOVE x TO something 

Тогда начальное значение просто путаница, ненужный, никогда не нужно, так как никогда ничего не заметит, что имеет, что начальное значение.

GnuCOBOL будет/может давать определенные начальные значения хранения в зависимости от типа данных. Это не обязательно переносится на другие компиляторы COBOL, поэтому на него не следует полагаться. Явная инициализация, только когда это необходимо, также указывает будущим читателям, что вы знаете, что делаете.

Вы забыли завершить свою программу.Поскольку вы забыли закончить его, управление просто запускается, прибыв в ваш последний пункт calculation, прежде чем окончательно отказаться от конца вашей программы. GnuCOBOL не имеет реальной проблемы с этим, но опять-таки это поведение не переносимо, и вам повезло, что код, который упал, ничего не меняет, когда он выполняется на этом этапе программы.

Кроме этого, я рекомендую избегать ненужных полных остановок/периодов в разделе ПРОЦЕДУРА. Проверка ошибок на вашем входе. Использование лучших имен. Первоначально ваш множитель и множитель, но это хорошая и ясная вещь, чтобы называть их во всей программе?

Вот ваша программа с требуемыми полными остановками/периодами в разделе ПРОЦЕДУРА, инициализация и условие завершения.

identification division. 
    program-id. multiplication. 
    data division. 
    working-storage section. 
    01 multiplier picture 9(36). 
    01 multiplicand picture 9(36). 
    01 answer picture 9(36) VALUE ZERO. 
    procedure division. 
     display 'multiplier?' 
     accept multiplier 
     display 'multiplicand?' 
     accept multiplicand 
     perform calculation 
      until multiplier = 0 
     display answer 
     goback (or stop run or exit program) 
     . 

    calculation. 
     if ((function mod(multiplier, 2)) = 1) then 
      add multiplicand to answer 
     end-if 
     divide 2 into multiplier 
     multiply 2 by multiplicand 
     . 
+0

Вопрос без уведомления: существует ли максимальная длина для поля 9s в GNUCobol или старый 9 (18), все еще принудительный (с последствиями компилятор-зависимость для текущего вопроса.) – Magoo

+0

@Magoo GnuCOBOL может выполнять 36 цифр. IBM может выполнить 31 вариант компилятора, с помощью расширения языка до стандарта 85. Текущий стандарт - 31. Для переносимости 18, возможно, были бы более надежными, хотя я бы предположил, что многие, если не все компиляторы позволят 31. Я не уверен, когда максимум 18 будет недостаточно :-) –

Смежные вопросы