Помогите исправить ошибку Process is terminated due to StackOverflowException

251
25 марта 2018, 18:34

Делаю лабораторную работу, задание:

Задание: 1) Создать программу рекурсивного поиска корня методом проб. 1) Написать рекурсивную процедуру/функцию для решения задачи, условие которой приведено ниже. Использовать динамический одномерный массив. Нарисовать полное дерево рекурсивных вызовов для N=8 Подсчитать для этого дерева глубину вызовов и объем рекурсии.

Варианты заданий: 8.Для заданного одномерного массива X из N элементов проверить, что для всех элементов массива выполняется условие cos Xi > 0. В рекурсивной функции каждый раз делить рассматриваемую часть массива на две части: одну треть и две третьих, проверяя условие с помощью этой же функции сначала в левой части (1/3), а затем при необходимости и в правой части. Рекурсивные вызовы заканчивать, когда останется только один или два элемента в рассматриваемой части массива.

На с# получился такой код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace programm
{
    class Program
    {
        class Mass
        {
            public double[] A;//Объявление массива 
            public Mass(int N)//Конструктор класса. В параметрах передается количество элементов массива (введенное в main)
            {
                A = new double[N];//Инициализация динамического массива (трудоемкость 1)
                Random rand = new Random();//Объявление и инициализация класса Random (трудоемкость 1)
                for (int i = 0; i < N; i++)//Цикл заполнения массива случайными значениями (трудоемкость всего цикла 1+3n+3n)
                    A[i] = rand.Next(-100, 100); //(трудоемкость 3)
            }
            public int Cos(int first, int last)//Получаем индексы первого и последнего элемента массива (подмассива).
            {
                if (last+1-first < 3)//Проверяем остался ли в подмассиве один или два элемента (трудоемкость 3, условие выполнится N раз)
                {
                    if (Math.Cos(A[first]) < 0)//Проверяем условие задачи (трудоемкость 4)
                        return 1;//Возвращаем 1 (трудоемкость 1)
                    else return 0;//Иначе, возвращаем 0 (трудоемкость 1)
                }
                else//Иначе
                    return Cos(first, (first + last) / 3) + Cos((first + last) / 3, last);//Вызываем функцию для первой трети и остальной части массива и складываем их результаты. (трудоемкость 11)
            }
        }
        static void Main(string[] args)
        {
            int N;
            Console.WriteLine("Введите N"); //(трудоемкость 1)
            N = Convert.ToInt32(Console.ReadLine());//Ввод количества элементов (трудоемкость 4)
            Mass M = new Mass(N);//Создание экземпляра класса. (трудоемкость 2)
            Console.WriteLine(M.Cos(0, N - 1));//Вызов метода Cos и вывод результата на экран. (трудоемкость 5)
            Console.ReadLine();
        }
    }
}
/*
Итоговая трудоемкость функции main равна: 12.
Используя метод апроксимации, получим 0.
Итоговая трудоемкость конструктора равна:6N+6.
Используя метод апроксимации, получим N.
Итоговая трудоемкость функции Cos: 20N-12.
Используя метод апроксимации, получим N.
Итого N.
*/

При запуске и вводе числа 8 получаю ошибку

Process is terminated due to StackOverflowException

:

Введите N
8
Process is terminated due to StackOverflowException.

Помогите пожалуйста понять, что я делаю не так?

Answer 1

Ваша проверка на рекурсию неправильная. Например, для случая first = 0, last = 2 у вас индекс «внутреннего» элемента равен (first + last) / 3 == first, то есть рекурсивный вызов Cos((first + last) / 3, last) будет с теми же аргументами.

Судя по всему, ваш интервал от first до lastполуоткрытый, то есть, ваши элементы начинаются от first и заканчиваются на last - 1. Если так, то ваша проверка на длину подмассива неверна: нужно вместо last+1-first < 3 просто last - first < 3.

Затем, у вас совершенно неверное вычисление делящего элемента. Если, например, first = 30, last = 33, ваше вычисление даст значение 21, которое не ледит между 30 и 33! Вычисляйте так:

else //Иначе
{
    int middle = first + (last - first) / 3;
    return Cos(first, middle) + Cos(middle, last);
}

Да, и вызывать нужно так:

Console.WriteLine(M.Cos(0, N));
READ ALSO
Парсинг значения json с помощью Newtonsoft на с#

Парсинг значения json с помощью Newtonsoft на с#

Задача: получить значение "lastPriceProtected"

346
c# awesomium отобразить webview в webcontrol

c# awesomium отобразить webview в webcontrol

Здравствуйте, подскажите, пожалуйста, использую awesomium с помощью webview

209
c# парсинг файлов multipart form data

c# парсинг файлов multipart form data

клиент на андроиде передает multipart/form-data данные серверу на c# строковые данные извлекаются без проблем, а вот файлы разобрать не могу android использует...

256