FOR/NEXT 有多个下一个命令

FOR/NEXT with multiple next commands

我必须在 BASIC 中编写 pi 的计算程序。为此,我使用 BASIC 的 FOR ... TO ... STEP 构造。

此外,我使用了 2 个 NEXT 命令,最后一个失败了。看起来它只是在程序达到循环极限时才失败。

我的代码如下所示:

2040 LET M = 0
2050 LET P = 3
2070 FOR i = 1 TO 50 STEP 2
2075 IF M = 1 THEN 2100
2080 P = P + 4/(I*(I+2)*(I+3))
2085 M = 1
2089 PRINT P
2090 NEXT i
2100 P = P - 4/(I*(I+2)*(I+3))
2105 M = 0
2109 PRINT P
2110 NEXT i

预期结果是这样的列表:

3.2981943981943984
3.2994764494764497
3.2986049897814604
3.2992241848279003
3.2987685001616893

and so on...

我得到的错误(仅当 i 达到 50 时):

next without for in line 2110

或者,在另一个环境中

E6 at 2110 FOR/NEXT error

我在网上找不到太多有用的文档,只有基本的 FOR ... TO ... STEP ... NEXT

是的,您只能有一个 NEXT 语句。相反,使用 IF .. THEN .. ELSE .. END IF 进行两种类型的计算。

2040 LET M = 0
2050 LET P = 3
2070 FOR i = 1 TO 50 STEP 2
2075 IF M <> 1 THEN 
2080 P = P + 4/(I*(I+2)*(I+3))
2085 M = 1
2089 PRINT P
2090 ELSE
2100 P = P - 4/(I*(I+2)*(I+3))
2105 M = 0
2107 END IF
2109 PRINT P
2110 NEXT i

这里有两个问题。

第一个是由第 2075 行的(隐含的)GOTO 语句引起的。(用 Edsger Dijkstra 的话说,GOTO 语句是 considered harmful。)在您的 FOR 循环中,第 2080-2089 行和第 2100 行-2109 在每个奇数和偶数迭代中交替执行。由于循环运行了奇数次(准确地说是 25 次),因此它会在到达第 2090 行的 NEXT I 语句时结束。之后,程序将执行到第 2100-2109 行,然后在第 2 行失败2110 当它在没有 FOR 循环处于活动状态时遇到 NEXT 语句。

更好的方法是使用 IF...THEN...ELSE 结构来控制 FOR 循环内的流程,或者简单地将 M 的值合并到计算中,例如,通过将 M 初始化为4 在第 2040 行,在第 2080 行将 4 替换为 M,并将第 2085 行替换为 M = -M。这种方法还有一个好处就是pi的计算只发生in one line而不是两次

另一个问题是你的程序产生了错误的答案!看起来你正在使用 Nilakantha Somayaji 发现的无限级数计算 pi,如下所示:

           4       4       4
pi = 3 + ----- - ----- + ----- - ...
         2.3.4   4.5.6   6.7.8

但是在您的程序中,您计算​​的分母错误地​​为 1.3.4、3.5.6、5.7.8 等等。这是建议的重写,应该会给您带来更好的结果:

1000 LET M = 4
1010 LET P = 3
1020 FOR I = 1 TO 50 STEP 2
1030 P = P + M / ((I+1)*(I+2)*(I+3))
1040 M = -M
1050 PRINT P
1060 NEXT I

一个我一直用的生成PI的函数:

REM 4 * (1/1-1/3+1/5-1/7...)
REM 3.1415926
DEFDBL A-Z
L = 1
DO
    X = X + 1 / L - 1 / (L + 2)
    L = L + 4
    P = 4 * X
    PRINT P
LOOP
END

另一种使用atn计算n位圆周率的算法:(仅在qb64中有用): 用途:16*阿坦(1/5)-4*阿坦(1/239)

DECLARE SUB atan239 (denom&)
DECLARE SUB atan5 (denom&)
DECLARE SUB PrintOut (words&)

DEFLNG A-Z
CLS
DIM SHARED digits AS LONG
start:
INPUT "How many digits(10-32766)"; digits&
IF digits& >= 10 AND digits& <= 32766 THEN
    Eat$ = ""
ELSE
    PRINT "Invalid precision."
    GOTO start
END IF
words& = digits& \ 4 + 3
DIM SHARED sum&(words& + 1), term&(words& + 1)
start! = TIMER

'16*atan(1/5)
denom& = 3: firstword = 1: lastword = 2
sum&(1) = 3: term(1) = 3: sum&(2) = 2000: term(2) = 2000
DO UNTIL firstword >= words&
    CALL atan5(denom&)
    denom& = denom& + 2
LOOP

'-4*atan(1/239)
denom& = 3: firstword = 2: remainder& = 4
FOR x = 2 TO words&
    dividend& = remainder& * 10000 'crunch out 1st term
    term(x) = dividend& \ 239&
    remainder& = dividend& - term(x) * 239&
    sum&(x) = sum&(x) - term(x)
NEXT x
DO UNTIL firstword >= words&
    CALL atan239(denom&)
    denom& = denom& + 4
LOOP
FOR x = words& TO 2 STEP -1
    IF sum&(x) < 0 THEN 'release carries
        quotient& = sum&(x) \ 10000 'and borrows
        sum&(x) = sum&(x) - (quotient& - 1) * 10000
        sum&(x - 1) = sum&(x - 1) + quotient& - 1
    END IF
    IF sum&(x) >= 10000 THEN
        quotient& = sum&(x) \ 10000
        sum&(x) = sum&(x) - quotient& * 10000
        sum&(x - 1) = sum&(x - 1) + quotient&
    END IF
NEXT x
CALL PrintOut(words&)
PRINT "computation time: "; TIMER - start!; " seconds"
END 

SUB atan239 (denom&)
    SHARED words&, firstword
    remainder1& = term(firstword) 'first divide implicitly
    remainder2& = 0: remainder3& = 0: remainder4& = 0
    denom2& = denom& + 2: firstword = firstword + 1
    FOR x = firstword TO words&
        temp& = term(x)
        dividend& = remainder1& * 10000 + temp&
        temp& = dividend& \ 57121
        remainder1& = dividend& - temp& * 57121
        dividend& = remainder2& * 10000 + temp&
        temp2& = dividend& \ denom&
        remainder2& = dividend& - temp2& * denom&
        sum&(x) = sum&(x) + temp2&
        dividend& = remainder3& * 10000 + temp&
        temp& = dividend& \ 57121
        remainder3& = dividend& - temp& * 57121
        dividend& = remainder4& * 10000 + temp&
        temp2& = dividend& \ denom2&
        remainder4& = dividend& - temp2& * denom2&
        sum&(x) = sum&(x) - temp2&
        term(x) = temp&
    NEXT x
    firstword = firstword + 1
    IF term(firstword) = 0 THEN firstword = firstword + 1
END SUB

SUB atan5 (denom&)
    SHARED words&, firstword, lastword
    FOR x = firstword TO lastword + 1
        temp& = term(x)
        dividend& = remainder1& * 10000 + temp&
        temp& = dividend& \ 25
        remainder1& = dividend& - temp& * 25&
        term(x) = temp&
        dividend& = remainder2& * 10000 + temp&
        temp& = dividend& \ denom&
        remainder2& = dividend& - temp& * denom&
        sum&(x) = sum&(x) - temp&
    NEXT x
    FOR x = lastword + 2 TO words&
        dividend& = remainder2& * 10000
        temp& = dividend& \ denom&
        remainder2& = dividend& - temp& * denom&
        sum&(x) = sum&(x) - temp&
    NEXT x
    IF term(lastword + 1) > 0 AND lastword < words& THEN lastword = lastword + 1
    IF term(firstword) = 0 THEN firstword = firstword + 1
    denom& = denom& + 2
    remainder1& = 0: remainder2& = 0
    FOR x = firstword TO lastword + 1
        temp& = term(x)
        dividend& = remainder1& * 10000 + temp&
        temp& = dividend& \ 25
        remainder1& = dividend& - temp& * 25&
        term(x) = temp&
        dividend& = remainder2& * 10000 + temp&
        temp& = dividend& \ denom&
        remainder2& = dividend& - temp& * denom&
        sum&(x) = sum&(x) + temp&
    NEXT x
    FOR x = lastword + 2 TO words&
        dividend& = remainder2& * 10000
        temp& = dividend& \ denom&
        remainder2& = dividend& - temp& * denom&
        sum&(x) = sum&(x) + temp&
    NEXT x
    IF term(lastword + 1) > 0 AND lastword < words& THEN lastword = lastword + 1
    IF term(firstword) = 0 THEN firstword = firstword + 1
END SUB

SUB PrintOut (words&)
    PRINT "pi = 3."
    FOR i = 1 TO words& \ 3
        PRINT " ";
        PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 2))), 4);
        PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 3))), 4);
        PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(3 * (i - 1) + 4))), 4);
        IF i MOD 5 = 0 THEN PRINT "  :"; 12 * i
    NEXT i
    PRINT " ";
    FOR i = 3 * (words& \ 3) + 2 TO digits&
        IF i <= UBOUND(sum&) THEN
            PRINT RIGHT$("0000" + LTRIM$(STR$(sum&(i))), 4);
        END IF
    NEXT i
    PRINT: PRINT
END SUB
REM end of function
REM end of file