Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
st063
Зарегистрирован: 14.06.2007 Сообщения: 2
|
Добавлено: Чт Июн 14 2007 23:46 Заголовок сообщения: рисование фрактала |
|
|
Задание такое: нарисовать фрактал на множестве Мондельброта (Жулиа)
по формуле которую задаёт пользователь. среда разработки Visual C++
6.0.
Проблема заключается в том, как сделать так чтобы по формуле, введённой пользователем рисовался фрактал. Поясню:
формулу я считываю в строчном формате, упрощаю её по обратной польской записи, опять собираю, получаю формулу без скобок.
(формула не содержит никаких орераций, кроме +,-,*,/)
Пример:
x=(x+c)*(x*c-x) -> x*x*c-x*x+x*c*c-x*c
Все бы ничего, но я всё равно получаю строку. А вот как сделать так, чтобы программа работала со строкой я не знаю (ведь и "x" и "c" -комплексные и просто подставить не получается). В поисках решения написал свой класс complex, перегрузил орераторы для типов данного класса и думал всё, но нет. Я всё равно не могу использовать строку как формулу, как я не разбирал строку по символам и знакам. Кто знает, как можно это сделать подскажите, хотя бы алгоритм!!!!
И не знает ли кто-нибудь существует в C++ встроенная функция на подобии eval() в javascript, т.е. функция позволяющая обращаться к строке, как к формуле???!!!! |
|
Вернуться к началу |
|
|
Kefir
Зарегистрирован: 16.04.2005 Сообщения: 443 Откуда: Пермь
|
Добавлено: Пт Июн 15 2007 05:54 Заголовок сообщения: |
|
|
Во-первых, алгоритм обратной польской записи реализован неверно.
Во-вторых, в C++ есть класс "std:complex<double>" для реализации комплексных чисел. _________________ Самоловских Виталий aka Kefir |
|
Вернуться к началу |
|
|
st063
Зарегистрирован: 14.06.2007 Сообщения: 2
|
Добавлено: Пт Июн 15 2007 08:31 Заголовок сообщения: |
|
|
Я знаю про встроенный класс в с++, но работать предпочёл со своим, ибо
нужны только операции +,-,*/ для комплексных чисел(класс мой работает правильно, проверял на конкретных примерах).
По поводу польской записи, почему не правильно? я просто в примере привёл уже конечный результат, после оптимизации польской записи.
Пример:
x=(x+c)*(x*c-x) -> (польская запись) xc+*xc*x- ->(после оптимизации получаю упрощённое вырожение) x*x*c+c*x*c-x*x-c*x.
И не было бы проблем, если 'x' и 'c' были бы числами, просто заменяешь их в просе сборки на числа, а потом переводишь строку в число с плавающей точкой встроенной функцией Convert. Но я то работаю с комплексными числами, и как перевести char * в complex не знаю.
В этом и проблема. |
|
Вернуться к началу |
|
|
Kefir
Зарегистрирован: 16.04.2005 Сообщения: 443 Откуда: Пермь
|
Добавлено: Пт Июн 15 2007 08:52 Заголовок сообщения: |
|
|
Не понимаю, почему Вы предпочли свой класс, в то время как есть готовый.
Правильно выражение в обратной польской записи запишется как:
xc+xc*x-*
Парсится запроста. Только нужно реализовать стэк. Т.е. даже реализовывать не нужно. Нужно только воспользоваться.
Если встречается символ x или c, то значение соответствующее одной из этих переменных помещается в стек.
Если встречается +, достаются 2 значения из стэка, суммируются и результат помещается в стек.
Аналогично для -,*,/ _________________ Самоловских Виталий aka Kefir |
|
Вернуться к началу |
|
|
vir
Зарегистрирован: 17.05.2007 Сообщения: 24
|
Добавлено: Чт Июн 21 2007 11:00 Заголовок сообщения: |
|
|
Чёт даже интересно стало, как люди вообще на С++ что-то пишут, решил вот попробовать. Вот что получилось. Код не тестировался, набирался в блокноте.
Код: |
typedef Env map<string, complex<double> >;
class Expr {public: virtual complex<double> eval (Env env) const = 0;}
class EBin : public Expr {
public: comlex<double> getA() const { return this->a->eval () };
comlex<double> getB() const { return this->b->eval () };
protected: EBin (Expr *a, Expr *b) {
this->a = a;
this->b = b;
}
private: Expr *a;
Expr *b;
}
class EAdd : public EBin {
public: EAdd (comlex<double> a, comlex<double> b) : EBin (a, b) {};
complex<double> eval (Env env) const {
return this->getA () + this-> getB ();
}
}
class EMul : public EBin {
public: EAdd (comlex<double> a, comlex<double> b) : EBin (a, b) {};
complex<double> eval (Env env) const {
return this->getA () * this-> getB ();
}
}
class ESub : public EBin {
public: EAdd (comlex<double> a, comlex<double> b) : EBin (a, b) {};
complex<double> eval (Env env) const {
return this->getA () - this-> getB ();
}
}
class EDiv : public EBin {
public: EAdd (comlex<double> a, comlex<double> b) : EBin (a, b) {};
complex<double> eval (Env env) const {
return this->getA () / this-> getB ();
}
}
class ELit : public Expr {
public: ELit (comlex<double> val) { this->val = val }
complex<double> eval (Env env) const {
return this->val;
}
private: complex<double> val;
}
class EVar : public Expr {
public: EVar (string name) { this->val = val }
complex<double> eval (Env env) const { return env[name]; }
private: complex<double> val;
}
struct ParseRes {
Expr *val;
char *rest;
}
ParseRes parse (char *exp)
{
ParseRes res, next;
res = parse_mul (exp);
if (res.rest == exp)
return res;
for (;;) {
if (res.rest == '+') {
next = parse_mul (res.rest + 1);
res.val = new EAdd (res.val, next.val);
res.rest = next.rest
} if (res.rest == '-') {
next = parse_mul (res.rest + 1);
res.val = new ESub (res.val, next.val);
res.rest = next.rest
} else
break;
}
return res;
}
ParseRes parse_mul (char *exp)
{
ParseRes res, next;
res = parse_mul (exp);
if (res.rest == exp)
return res;
for (;;) {
if (res.rest == '*') {
next = parse_other (res.rest + 1);
res.val = new EMul (res.val, next.val);
res.rest = next.rest
} if (res.rest == '/') {
next = parse_other (res.rest + 1);
res.val = new EDiv (res.val, next.val);
res.rest = next.rest
} else
break;
}
return res;
}
ParseRes parse_other (char *exp)
{
ParseRes res, next;
res.rest = exp;
res.val = NULL;
if (isalpha (*exp)) {
string name = new string ("");
name += *exp++;
while (isalphanum (*exp))
string name += *exp++;
res.rest = exp;
res.val = new EVar (name);
} else if (isdigit (*exp)) {
complex<double> n = new complex<double> (0);
n += *exp++ - '0';
while (isdigit (*exp)) {
n *= 10;
n += *exp++ - '0';
}
if (*exp == '.') {
exp++;
int k = 1;
while (isdigit (*exp)) {
n *= 10;
k *= 10;
n += *exp++ - '0';
}
n /= k;
}
res.rest = exp;
res.val = new ELit (n);
} else if (*exp == '(') {
exp++;
next = parse (exp);
if (next.rest[0] == ')') {
res.rest = next.rest + 1;
res.val = next.val;
}
}
return res;
}
int main (int argc, char **argv) {
ParseRes res;
res = parse (argv[1]);
Env env = new Env ();
env["i"] = new complex<double> (0, 1);
cout << res.val->eval (env) << endl;
}
|
|
|
Вернуться к началу |
|
|
|