【问题标题】:program of multiplying large numbers, perform until loop not working in cobol乘以大数的程序,执行直到循环在 cobol 中不起作用
【发布时间】:2016-04-08 17:40:37
【问题描述】:

当我执行 x 次计算时,代码运行良好。但是,当我这样做时,乘数不会改变。我是 COBOL 的新手,所以我不确定我做错了什么。我基本上想要一个while循环,直到乘数大于0。由于cobol没有递归,我正在尝试这种方式,它在C中工作正常,但是它给我带来了关于循环方面的问题。

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 时吗?
  • 是的,抱歉。我应该使用while吗?
  • 或者“直到乘数
  • 你在哪里初始化答案?
  • 在 Cobol 中没有 while,只有直到(除非他们最近改变了这个)。您可以使用直到乘数 = 0,因为您已将变量定义为图 9,因此它们永远不会是负数。如果编译器支持 36 位数字的 comp,请尝试添加 comp 甚至更好的 comp-5

标签: cobol


【解决方案1】:

看起来您正在使用 GnuCOBOL(或较旧的 OpenCOBOL,GnuCOBOL 是 OpenCOBOL 的新名称)。 2002 COBOL 标准(现在被 2014 标准取代)向 COBOL 引入了递归(在 PROGRAM-ID 上是递归的),GnuCOBOL 支持递归,这在其他 COBOL 编译器中很常见。

除此之外,当有一个非曲折的替代方案时,为什么要对某事使用递归?

您有三个实际问题,其中两个已包含在您问题的 cmets 中。

直到。这意味着“在这种情况存在之前,继续执行 PERFORM”。它可以位于迭代的“顶部”(第一件事)或底部(最后一件事)。一旦条件为真,PERFORM 将不会执行。当条件最初为真时,PERFORM 是否执行取决于 WITH TEST。 WITH TEST BEFORE(默认)意味着如果遇到 PERFORM 时条件为真,则 PERFORM 根本不会执行。 WITH TEST AFTER 将测试延迟到第一次执行代码块(对于内联 PERFORM)或段落/部分完成。

遇到 PERFORM 时,multiplier 已经大于零。您使用 WITH TEST AFTER,因此您可以一键更改终止值。代码没有做任何事情来确保乘数不大于零,因此当终止条件为真时,将不会再次输入 PERFORMed 段落。

使用 EQUAL TO ZERO,放弃 WITH TEST AFTER。乘数不能为负数,也没有小数部分。当一除以二并存储结果时,该结果将为零。这肯定会在您的程序中每次都发生。这是你的终止条件。

您已经定义了答案,并将其作为加法的目标,但在加法之前没有保证值。在将其用作任何类型的计算目标之前,请将其设置为零(VALUE 子句,或 MOVE ZERO TO ... 或 INITIALIZE ...)。但是,如果它不需要初始值,则不要给它一个初始值。

如果第一次使用something是这样的:

ADD x TO something

那么你应该确保它有一个初始值。如果是这样:

MOVE x TO something

那么初始值只是一种混乱,不必要,永远不需要,因为没有人会注意到它具有初始值。

GnuCOBOL 将/可以根据数据类型给出定义的存储初始值。这不一定可移植到其他 COBOL 编译器,因此不应依赖它。显式初始化,仅在需要时,也向未来的读者表明您知道自己在做什么。

您忘记结束程序。因为您忘记了结束它,所以控制只是继续运行,最后一次到达您的calculation 段落,然后最终放弃您的程序结束。 GnuCOBOL 对此没有真正的问题,但同样,这种行为是不可移植的,你很幸运,当它在程序的那个阶段执行时,放入的代码没有任何改变。

除此之外,我建议避免在 PROCEDURE DIVISION 中使用不必要的句号/句号。对您的输入进行错误检查。使用更好的名称。您的乘数和被乘数最初是这样的,但是在整个程序中调用它们是一件好事和明确的事情吗?

这是您的程序,其中只有 PROCEDURE DIVISION 中所需的句号/句号,初始化和终止条件已更正。

   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 
       . 

【讨论】:

  • 问题恕不另行通知:GNUCobol 中的 9s 字段是否有最大长度,或者旧的 9(18) 是否仍然强制执行(暗示当前问题的编译器依赖性。)
  • @Magoo GnuCOBOL 可以做 36 位数字。 IBM 可以通过编译器选项,通过对 85 标准的语言扩展来完成 31。当前的标准是 31。为了可移植性,18 可能更可靠,尽管我猜如果不是所有编译器都会允许 31。我不确定什么时候最多 18 还不够 :-)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 2020-09-02
相关资源
最近更新 更多