2

I have to program a calculation of pi in BASIC. To do so, i use the FOR ... TO ... STEP construction of BASIC.

Also, i am using 2 NEXT commands, the last one fails. It looks like it only fails as the programm reached the limit of the loop.

My code looks like this:

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

The Excpected Result is a list like this:

3.2981943981943984
3.2994764494764497
3.2986049897814604
3.2992241848279003
3.2987685001616893

and so on...

The error i get (only if i reached 50):

next without for in line 2110

Or, at another environment

E6 at 2110 FOR/NEXT error

I dont find very much helpful documentation on the Web, only the basic FOR ... TO ... STEP ... NEXT.

MSauer
  • 148
  • 3
  • 11

4 Answers4

3

Yes, you can only have one NEXT statement. Instead, branch out with an IF .. THEN .. ELSE .. END IF for the two types of calculation.

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
John Alexiou
  • 28,472
  • 11
  • 77
  • 133
3

There are two problems here.

The first is caused by the (implied) GOTO statement at line 2075. (In the words of Edsger Dijkstra, GOTO statements are considered harmful.) In your FOR loop, lines 2080-2089 and lines 2100-2109 are alternately executed at every odd and even iteration. Since the loop runs an odd number of times (25, to be precise), it will finish when it reaches the NEXT I statement at line 2090. After that, the program will fall through to lines 2100-2109, and then fail at line 2110 when it encounters a NEXT statement when no FOR loop is active.

A better approach would be to use an IF...THEN...ELSE structure to control the flow within the FOR loop, or simply to incorporate the value of M into the calculation, e.g., by initializing M to 4 at line 2040, replacing 4 with M in line 2080, and replacing line 2085 with M = -M. This approach also has the advantage that the calculation of pi only takes place in one line instead of two.

The other problem is that your program produces the wrong answer! It looks like you're calculating pi using the infinite series discovered by Nilakantha Somayaji, which is as follows:

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

But in your program, you're calculating the denominators incorrectly as 1.3.4, 3.5.6, 5.7.8, and so on. Here's a suggested rewrite that should give you a better result:

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
r3mainer
  • 23,981
  • 3
  • 51
  • 88
0

A function to generate PI that I have always used:

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
eoredson
  • 1,167
  • 2
  • 14
  • 29
  • 2
    This algorithm uses the Gregory-Leibniz series, which converges on pi [much more slowly](https://helloacm.com/two-simple-equations-to-compute-pi/) than the OP's method. – r3mainer Nov 08 '19 at 11:07
  • Is there a QB program for PI using the Gauss-Legendre algorithm? – eoredson Nov 09 '19 at 04:32
  • 1
    I'm not familiar with QB, but the algorithm is simple enough: https://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm#Algorithm – r3mainer Nov 09 '19 at 22:47
0

Another algorithm using atn to calculate n digits of pi: (usefull in qb64 only): Uses: 16*atan(1/5)-4*atan(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
eoredson
  • 1,167
  • 2
  • 14
  • 29