为什么我的COBOL工作存储变量具有尾声零?

发布于 2025-02-06 01:05:12 字数 1829 浏览 1 评论 0原文

我正在构建一个COBOL计划,以计算最多15个整数的平均值。该执行显示的数字远远超过了许多尾随零。这是相关代码:

       Data Division.
       Working-Storage Section.
       01 WS-COUNTER          PIC 9(10).
       01 WS-INPUT-TOTAL      PIC 9(10).
       01 WS-NEXT-INPUT       PIC X(8).
       01 WS-CONVERTED-INPUT  PIC 9(8).
       01 WS-AVG              PIC 9(8)V99.

       Procedure Division.
       PROG.
           PERFORM INIT-PARA
           PERFORM ADD-PARA UNTIL WS-COUNTER = 15 OR WS-NEXT-INPUT = 'q'
           PERFORM AVG-PARA
           PERFORM END-PARA.
       INIT-PARA.
           DISPLAY 'This program calculates the average of inputs.'.
           MOVE ZERO TO WS-COUNTER
           MOVE ZERO TO WS-INPUT-TOTAL
           MOVE ZERO TO WS-AVG.
       ADD-PARA.
           DISPLAY 'Enter an integer or type q to quit: '
           ACCEPT WS-NEXT-INPUT
           IF WS-NEXT-INPUT NOT = 'q'
               MOVE WS-NEXT-INPUT TO WS-CONVERTED-INPUT
               ADD WS-CONVERTED-INPUT TO WS-INPUT-TOTAL
               ADD 1 TO WS-COUNTER
           END-IF.
       AVG-PARA.
           IF WS-COUNTER > 1
               DIVIDE WS-INPUT-TOTAL BY WS-COUNTER GIVING WS-AVG
               DISPLAY 'Your average is ' WS-AVG '.' WS-NEXT-INPUT
           END-IF.

我将ws-next-input作为字母数字放置的原因,并将其移至数字ws-converted-Input如果如果条件是因为我希望它能够将“ Q”打破直至循环,但是在满足条件后,我想要一个数字变量,用于算术语句。这就是数字10和15作为输入的外观:

10is program calculates the average of inputs.
Enter an integer or type q to quit:
15
Enter an integer or type q to quit:
q
Your average is 1250000000.

控制台有点障碍,因此它迫使我大部分时间都在左上角输入10个。不用担心。

您会在执行中看到我的问题。结果应该是00000012.50,而不是1250000000。我尝试将我的其他一些变量插入该显示语句,它们基本上应该是,除了WS-Input-total,它们的数字的组合最终是0025000000,而不是0000000025。为什么这些数字以如此怪异和出乎意料的方式存储?

I'm building a COBOL program to calculate the average of up to 15 integers. The execution displays a number that is far bigger than intended with a lot of trailing zeroes. Here is the relevant code:

       Data Division.
       Working-Storage Section.
       01 WS-COUNTER          PIC 9(10).
       01 WS-INPUT-TOTAL      PIC 9(10).
       01 WS-NEXT-INPUT       PIC X(8).
       01 WS-CONVERTED-INPUT  PIC 9(8).
       01 WS-AVG              PIC 9(8)V99.

       Procedure Division.
       PROG.
           PERFORM INIT-PARA
           PERFORM ADD-PARA UNTIL WS-COUNTER = 15 OR WS-NEXT-INPUT = 'q'
           PERFORM AVG-PARA
           PERFORM END-PARA.
       INIT-PARA.
           DISPLAY 'This program calculates the average of inputs.'.
           MOVE ZERO TO WS-COUNTER
           MOVE ZERO TO WS-INPUT-TOTAL
           MOVE ZERO TO WS-AVG.
       ADD-PARA.
           DISPLAY 'Enter an integer or type q to quit: '
           ACCEPT WS-NEXT-INPUT
           IF WS-NEXT-INPUT NOT = 'q'
               MOVE WS-NEXT-INPUT TO WS-CONVERTED-INPUT
               ADD WS-CONVERTED-INPUT TO WS-INPUT-TOTAL
               ADD 1 TO WS-COUNTER
           END-IF.
       AVG-PARA.
           IF WS-COUNTER > 1
               DIVIDE WS-INPUT-TOTAL BY WS-COUNTER GIVING WS-AVG
               DISPLAY 'Your average is ' WS-AVG '.' WS-NEXT-INPUT
           END-IF.

The reason I put WS-NEXT-INPUT as alphanumeric and move it to a numeric WS-CONVERTED-INPUT if the IF condition is satisfied is because I want it to be able to take "q" to break the UNTIL loop, but after the condition is satisfied, I want a numeric variable for the arithmetical statements. Here's what it looks like with the numbers 10 and 15 as inputs:

10is program calculates the average of inputs.
Enter an integer or type q to quit:
15
Enter an integer or type q to quit:
q
Your average is 1250000000.

The console is a bit buggy so it forces me to input the 10 in that top left corner most of the time. Don't worry about that.

You see my problem in that execution. The result is supposed to be 00000012.50 instead of 1250000000. I tried inserting a few of my other variables into that display statement and they're all basically as they should be except for WS-INPUT-TOTAL which with that combination of numbers ends up being 0025000000 instead of 0000000025 as I would have expected. Why are these digits being stored in such a weird and unexpected way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猥琐帝 2025-02-13 01:05:12

由于行为不确定 - 使用空间计算,您的输出具有奇怪的输出。

移动您出席的具有完全相同的 usage 和相同的大小 - 通常将其按照“原样”进行,通常不会通过某些魔法转换后线空间,因此,WS转换输入最终以10。正如标准所说的那样:

脱编辑仅在发送操作数是数字编辑的数据项时才进行,并且接收项是数字或数字编辑的数据项。

如果它是编辑的字段,那么它仍然应该在移动上提出一个例外:

当数字编辑的数据项是编辑移动语句的发送操作数,并且该数据项的内容是该数据项中任何编辑操作的可能结果,这是移动的结果操作是未定义的,ec-data compatible异常条件已设置为

当使用空间计算时,您通常会引起致命错误,但是您的编译似乎没有被激活(并且因为您没有共享编译命令甚至编译器,所以我们无能为力)。

不同的COBOL方言经常使用(仅在未激活检查时部分使用,这将导致中止)对于无效的数据零,至少对于空格而言(但是它们 can 使用所有内容。 > WS转换输入“被视为“ 10000000 - 因此,您的计算将包括这些大数字,

因此如果您输入输入中必要的领先零数量,则可以使用。

  • “永不信任输入数据 - 验证”(以及必要的错误或转换),
  • 如果某些东西看起来可疑 - 激活所有运行时检查,请重新尝试。

常规

至少 - 接收到)到WS转换输入,这将剥离周围的空间,然后从左到右转换,直到找到无效的数据,也将使用功能测试 - numval,否则,如果某人进入“二十”,则使用零计算。

You have that strange output because of undefined behavior - computing with spaces.

The MOVE you present has the exact same USAGE and same size - it will commonly be taken over "as is", it normally does not convert the trailing spaces by some magic, so WS-CONVERTED-INPUT ends up with 10. As the standard says for the move:

De-editing takes place only when the sending operand is a numeric-edited data item and the receiving item is a numeric or a numeric-edited data item.

and if it would be an edited field then it still should raise an exception on the MOVE:

When a numeric-edited data item is the sending operand of a de-editing MOVE statement and the content of that data item is not a possible result for any editing operation in that data item, the result of the MOVE operation is undefined and an EC-DATA-INCOMPATIBLE exception condition is set to exist.

When computing with spaces you commonly would raise a fatal error, but it seems your compile does not have that activated (and because you didn't share your compile command or even your compiler, we can't help with that).

Different COBOL dialects often use (partial only when checks are not activated which would lead to an abort) zero for invalid data, at least for spaces (but they can use everything. This will then lead to WS-CONVERTED-INPUT "seen as" 10000000 - so your computation will then include those big numbers.

So your program should work if you enter the necessary amount of leading zeroes on input.

General:

  • "never trust input data - validate" (and error or convert as necessary)
  • at least if something looks suspicious - activate all runtime checks available, re-try.

Solution - Do an explicit conversion:

MOVE FUNCTION NUMVAL(WS-NEXT-INPUT) TO WS-CONVERTED-INPUT, this will strip surrounding spaces and then convert from left to right until invalid data is found. A good coder would also check up-front using FUNCTION TEST-NUMVAL, otherwise you compute with zero if someone enters "TWENTY".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文