Поиск подстроки работает некорректно

Модифицирую учёбное упражнение по поиску приблизительного значения числа π из сборника Стивенсона.

Вот что требовалось обычно:

mltp = 1; pi=3; a=2;
for i in range(2,170):
    for d in range(a,a+3):
        mltp*=d;
    slg=4/mltp;
    a+=2; mltp=1;
    if i%2==0:
        pi+=slg;       
    else: pi-=slg;
print("Число пи равно", pi);

С этим проблем не возникло. Затем я решил усложнить задачу: сколько раз нужно провести вычисления, чтобы получить точность до 7 знака. Стишок числа π же знаем? Значение 170 я подобрал вручную, а может, вычислений нужно меньше. Для автоматического поиска я усложнил код до такого:

mltp = 1;
pi="3.00000000";
a=2;
r=2;
print("loop is a go");
while "3.1415926" not in pi:
    r+=1;
    for i in range(2,r):
        for d in range(a,a+3):
            mltp*=d;
        slg=4/mltp;
        a+=2; mltp=1;pi=float(pi);
        if i%2==0:
            pi+=slg;       
        else: pi-=slg;
    pi=str(pi);
print("Число пи равно", pi);
print(f"Нужная точность была достигнута в {r}-приближении");

Проблема возникла с заданием условия цикла while. Вот в чём это выражается: При любом из:

while "3.1415926" in pi:
while "14" in pi:

получаю на выходе:

Число пи равно 3.00000000

Нужная точность была достигнута в 2-приближении

При:

while "3.1415926" not in pi:

Получается вообще бесконечный цикл.

Далее ещё интереснее: Я поставил:

while "14" not in pi:

И получил весьма неожиданный результат:

Число пи равно 3.1933003260144996

Нужная точность была достигнута в 10-приближении

То есть очевидно программа ищет подстроку вообще не с начала и поэтому работает неправильно. Почему так? Как написать правильное условие? Заранее благодарю.

Переделал цикл while, чтобы посмотреть, что там за счёт происходит и был очень удивлён:

while r!=5:
    r+=1; a=2; 
    if r in range(0,200,10):
        print(f"Пошло приближение {r}");
    for i in range(2,r):
        mltp=1; slg=0;
        for d in range(a,a+3):
            mltp*=d;
        slg=4/mltp; print("Слагаемое %.2f" %slg, "с делителем ", mltp, end=' ');
        a+=2; pi=3;
        if i%2==0:
            pi+=slg; print("и оно прибавляется ",pi);       
        else: pi-=slg; print("и оно вычитается ",pi);
    #pi=str(pi);
    print(f"Число пи равно {pi} c делителем {mltp} на шаге {r}");
print(f"Нужная точность была достигнута на {r} шаге");

На выходе получаю:

Слагаемое 0.17 с делителем 24 и оно прибавляется 3.1666666666666665

Число пи равно 3.1666666666666665 c делителем 24 на шаге 3

Слагаемое 0.17 с делителем 24 и оно прибавляется 3.1666666666666665

Слагаемое 0.03 с делителем 120 и оно вычитается 2.966666666666667

Я даже вручную сделал проверку

3.1666666666666665-0.03

3.1366666666666667


Ответы (1 шт):

Автор решения: CrazyElf

Не нужно гонять pi в строку и обратно каждый раз, достаточно это делать во время вашей проверки.

mltp = 1; pi=3; a=2;
i = 2
while "3.1415926" not in str(pi):
    for d in range(a,a+3):
        mltp*=d;
    slg=4/mltp;
    a+=2; mltp=1;
    if i%2==0:
        pi+=slg;       
    else: pi-=slg;
    i += 1
print("Число пи равно", pi);
print(f"Нужная точность была достигнута в {i-2}-приближении");

Вывод:

Число пи равно 3.141592601798008
Нужная точность была достигнута в 168-приближении
→ Ссылка