2

我正在尝试编写一个程序来为我求和一个数组,但是当我尝试运行单词 sum 时,它一直给我一个非常长的数字,类似于一个地址。我尝试将它拆开并在终端中的单词之外逐行运行并手动循环工作正常,但是当我真正让它工作时它完全失败了。我究竟做错了什么?

variable length \ length var declared
create list \ space for my list made
0 variable cumsum  \ sum value initialized to zero

: upload     ( n1 n2 n3 --) \ loops thru and stuffs data into array
depth        ( n1 n2 n3 -- n1 n2 n3 depth) \ get depth
length !     ( n1 n2 n3 depth -- n1 n2 n3) \ array length stored
list         ( n1 n2 n3 -- n1 n2 n3 addr)
length @     ( n1 n2 n3 addr -- n1 n2 n3 addr nlength)
cells allot  ( n1 n2 n3 addr nlength -- n1 n2 n3) 
length @ 1+  ( n1 n2 n3 -- n1 n2 n3 nlength) \ consume all entries
0            ( n1 n2 n3 nl -- n1 n2 n3 nl 0) \ lower loop parameter..
do           ( n1 n2 n3 nl 0 -- n1 n2 n3) \ loop begins
list         ( n1 n2 n3 -- n1 n2 n3 addr)
I            ( n1 n2 n3 addr -- n1 n2 n3 addr I) \ calculating address
cells        ( n1 n2 n3 addr I -- n1 n2 n3 addr Ibytes)
+            ( n1 n2 n3 addr Ibytes -- n1 n2 n3 addr1+)
!            ( n1 n2 n3 addr1+ -- n1 n2) \ storing into calculated address
loop
;

上传就像一个魅力,但后来我去使用这个词

: sum ( n1 n2 n3 -- nsum)
upload \ initiates the array
length @  \ invokes upper limit of loop
0        \ lower limit of loop
do
list          ( -- addr)        \ addr invoked
I cells +     ( addr -- addr+)  \ offset calculated and added
@             ( addr+ -- nl)    \ registered value at address fetched
cumsum @      ( nl -- nl ncs)   \ cum sum value fetched to stack
+             ( nl ncs -- nsum) \ summation
cumsum !      ( nsum --)        \ new sum written to cumsum
loop
cumsum ?      ( -- cumsum)      \ show sum
;

它返回一个非常长的数字,看起来像一个地址,而不是我添加来测试它的一些小数字列表的总和。

1  ok
2  ok
3  ok
sum 140313777201982  ok
4

3 回答 3

2

因此,如果我理解正确,问题是:

  1. 将堆栈上的所有数字存储到一个数组中。
  2. 将存储在数组中的所有数字相加。

我会做这样的事情:

: upload ( ... "name" -- ) create depth dup ,  0 ?do , loop ;
: sum ( a -- n ) 0 swap @+ 0 ?do @+ rot + swap loop drop ;

像这样使用:

1 2 3 4 upload array
array sum .
于 2015-06-05T05:58:17.900 回答
1

UPLOAD你执行LIST LENGTH @ CELLS ALLOT. ALLOT在当前字典或数据空间指针处分配内存,而不是在LIST. ALLOT不消耗堆栈中的起始地址。实际上,上面代码片段中 LIST 返回的地址稍后会!在您的数组填充循环中使用。这是第一个数组单元格的数据。因此,您的地址如返回的数字SUM

最好是保持CREATEALLOT在一起。在创建 LIST 和执行 ALLOT 之间发生了一些字典添加。您的数组单元格可能不是 LIST 指向的位置。

一般来说,变量不会消耗堆栈中的数字。大多数情况下,它们会自动初始化为0. 0 VARIABLE CUMSUM堆栈上的保留为零也是如此。如果您一次性运行或键入代码,DEPTH这会产生后果。LENGTH尽量避免DEPTH,更好的是明确告诉数组定义单词你想要多少项目,例如:
CREATE LIST 3 CELLS ALLOT

顺便说一句,在 SwiftForth 中运行您的代码,我在SUM. 之后我在字典中存储了 5 个项目 ( LENGTH @ 1+in UPLOAD) LIST,覆盖了字典主目录的部分内容CUMSUM...

Lars Brinkhoff 展示了一个不错的选择,除此之外DEPTH是 ;-)

于 2015-06-05T12:34:56.023 回答
0

主要问题是@roelf 解释的。我将添加两个兴趣点。

1) 你怎么知道有什么不对劲?当你遇到这样的问题时,检查内存——做一个十六进制转储!

1 2 3 sum -1223205794  ok
list 32 dump 
B7175C58: 58 5C 17 B7  03 00 00 00 - 02 00 00 00  01 00 00 00  X\..............
B7175C68: 00 00 00 00  00 00 00 00 - 5E 5C 17 B7  58 5C 17 B7  ........^\..X\..
 ok

您可以看到列表的第一个单元格是垃圾。所以也许upload毕竟没有那么好用!

2)请注意,如果您只想在堆栈上添加所有值,则不需要将命名空间与变量混为一谈:

: sum depth 1 do + loop ;
于 2015-07-29T09:09:35.897 回答