FOR / NEXT с несколькими следующими командами - PullRequest
2 голосов
/ 07 ноября 2019

Я должен запрограммировать расчет пи в бейсике. Для этого я использую FOR ... TO ... STEP конструкцию BASIC.

Кроме того, я использую 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.

Ответы [ 4 ]

2 голосов
/ 08 ноября 2019

Здесь есть две проблемы.

Первая вызвана (подразумеваемым) оператором GOTO в строке 2075. (По словам Эдсгера Дейкстры, операторы GOTO считаются вредными . ) В цикле FOR строки 2080-2089 и 2100-2109 поочередно выполняются на каждой нечетной и четной итерации. Поскольку цикл выполняется нечетное число раз (25, если быть точным), он завершится, когда достигнет оператора NEXT I в строке 2090. После этого программа провалится в строки 2100-2109, а затем потерпит неудачу в строке2110, когда он встречает оператор NEXT, когда цикл FOR не активен.

Лучшим подходом было бы использование структуры IF ... THEN ... ELSE для управления потоком внутри цикла FOR или просто длявключить значение M в расчет, например, инициализируя M в 4 в строке 2040, заменяя 4 на M в строке 2080 и заменяя строку 2085 на M = -M. Этот подход также имеет то преимущество, что вычисление числа «пи» происходит только в одной строке вместо двух.

Другая проблема заключается в том, что ваша программа выдает неправильный ответ! Похоже, вы вычисляете число Пи, используя бесконечный ряд, обнаруженный Нилаканта Сомаяджи , который выглядит следующим образом:

           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
2 голосов
/ 08 ноября 2019

Да, вы можете иметь только один оператор 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
0 голосов
/ 15 ноября 2019

Другой алгоритм, использующий atn для вычисления n цифр числа pi: (полезно только в qb64): Использует: 16 * atan (1/5) -4 * atan (1/239)

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

DEFLNG A-Z
CLS
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 " ";
    PRINT: PRINT
END SUB
0 голосов
/ 08 ноября 2019

Функция для генерации 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
...