Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как написать красиво? 
:(
    Опции темы
Kakadu
Дата 7.10.2008, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 273
Регистрация: 19.3.2008

Репутация: нет
Всего: 7



Код

// вот собственно код.
// Хочу брать производную от функции, представленной в виде дерева.
using System;
using System.Collections.Generic;
using System.Text;

namespace Felisitas {
    /// <summary>
    /// Дерево для представления функции в обратной польской записи.
    /// </summary>
    class EquationTree {
        public Node root;
        public EquationTree(object r) {
            root = (Node)r;
        }
    }
    class Node : ICloneable {
        public string FuncName = "";
        public List<Node> Sons = new List<Node>();

        public object Clone() {
            Node ans = new Node(this.FuncName);
            foreach (Node nod in this.Sons) 
                ans.Sons.Add((Node)nod.Clone());
            return ans;
        }
        public Node() {
        }
        public Node(string name) {
            FuncName = name;
        }
        public Node(string name, List<Node> lst) {
            FuncName = name; Sons = lst;
        }
        public void AddChild(Node child) {
            Sons.Add(child);
        }
    }

    /// <summary>
    /// Класс должен помогать брать производную от функции.
    /// </summary>
    class Derivative {
        /// <summary>
        /// Проверка, является ли рассматриваемая строка - функцией.
        /// </summary>
        /// <param name="s">Рассматриваемая строка</param>
        /// <returns>0 - если это название какой-то переменной, -1 - для константы,
        /// иначе - число параметров у данной функции</returns>
        private int IsFunc(string s) {
            Double d;
            if (Double.TryParse(s, out d))
                return -1;
            switch (s) {
                case "+":
                case "-":
                case "*":
                case "/": return 1;
                case "cos":
                case "sin":
                case "ln":
                case "tan": return 2;
            }
            return 0;
        }
        /// <summary>
        /// Функция строит дерево по обратной польской записи
        /// </summary>
        /// <param name="polish">Польская запись</param>
        /// <returns>null если ошибка, иначе ссылку на готовой дерево</returns>
        private EquationTree BuildTree(List<string> polish) {
            Stack<Node> args = new Stack<Node>();
            Node NewNode;

            foreach (string s in polish) {
                int ArgsCount=IsFunc(s);
                NewNode = new Node(s);
                for (int i = 0; i < ArgsCount; ++i) 
                    NewNode.AddChild(args.Pop());
                args.Push(NewNode);
            }
            if (args.Count != 1) 
                System.Windows.Forms.MessageBox.Show("Лажа с польской строкой");
            else 
                return new EquationTree(args.Pop());
            return null;
        }

        // Вот это и есть функция, берущая производную. Она рекурсивно вызывается для каждого
        // аргумента функции, которая ей передаётся
        // Извините, что так коряво сказал......
 
        /// <summary>
        /// Генерирует дерево производной по дереву функции.
        /// </summary>
        /// <param name="nod">Cсылка на корень</param>
        /// <returns></returns>
        private Node GenDeriv(Node nod) {
            Node newNode = null;
            Double d;
            if (Double.TryParse(nod.FuncName, out d)) {
                newNode = new Node("0");
                return newNode;
            }
            Node tmpNode1, tmpNode0, tmpNode2;
            switch (nod.FuncName) {
                case "+":
                    newNode = new Node("+");
                    newNode.AddChild(GenDeriv(nod.Sons[0]));
                    newNode.AddChild(GenDeriv(nod.Sons[1]));
                    break;
                case "-":
                    newNode = new Node("-");
                    newNode.AddChild(GenDeriv(nod.Sons[0]));
                    newNode.AddChild(GenDeriv(nod.Sons[1]));
                    break;
                case "*":
                    newNode = new Node("+");
                    newNode.Sons.Add(tmpNode0 = new Node("*"));
                    newNode.Sons.Add(tmpNode1 = new Node("*"));
                    tmpNode0.AddChild((Node)nod.Sons[0].Clone());
                    tmpNode1.AddChild((Node)nod.Sons[1].Clone());
                    tmpNode0.AddChild(GenDeriv(nod.Sons[1]));
                    tmpNode1.AddChild(GenDeriv(nod.Sons[0]));
                    break;
                case "/":
                    tmpNode0 = nod.Sons[0];
                    tmpNode1 = nod.Sons[1];
                    newNode = new Node("/");
                    newNode.AddChild(new Node("/"));
                    newNode.AddChild((Node)tmpNode1.Clone());
                    newNode.Sons[0].AddChild(new Node("-"));
                    newNode.Sons[0].AddChild((Node)tmpNode1.Clone());
                    tmpNode2 = newNode.Sons[0].Sons[0];
                    tmpNode2.AddChild(new Node("*"));
                    tmpNode2.AddChild(new Node("*"));
                    tmpNode2.Sons[0].AddChild(GenDeriv(tmpNode0));
                    tmpNode2.Sons[0].AddChild((Node)tmpNode1.Clone());
                    tmpNode2.Sons[1].AddChild(GenDeriv(tmpNode1));
                    tmpNode2.Sons[1].AddChild((Node)tmpNode0.Clone());
                    break;
            }
            return newNode;
        }
    }
}




--------------------
Добрые мариносы долго кормили украдкой маленьких зерлингов. От этой украдки зерлинги пухли и дохли
PM MAIL   Вверх
Zakonnic
Дата 8.10.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 25.4.2006

Репутация: 2
Всего: 6



IMHO:
1. Метод BuildTree лучше сделать конструктором класса EquationTree (коль скоро там new всегда вызывается)
2. Для обработки исключений не месседж-боксы надо выдавать, а генерировать эксепшн, который уже обрабатывать во внешней функции. Короче для реюзабельности кода мессадж-боксы не годятся.
3. Лучше назвать класс не Derivative а Expression или как-то так, потому что нет у него специфичных для производной свойств. Тогда просто у "Выражения" будет метод "ВзятьПроизводную", которая тоже будет выражением. Либо если особые свойства есть (например, порядок производной), то класс Derivative наследовать от Expression, а метод сделать конструктором. Или не делать, но конструктор с его вызовом объявить можно.
--------------------
...и никогда не пишите в комментариях правду
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0414 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.