PDA

View Full Version : Expression Manipulator v0.1



ygfperson
05-15-2003, 11:37 PM
It's finally here... after a month... :D

It's got plenty of bugs to be worked out... but this is pretty far along from my last release.

This is a set of classes designed to manipulated Expressions, functions, and what-have-you.

Features:

Expressions can be typed in almost as they would be on a graphing calculator
The classes are const-protected; with private parts protected
It will accept equations, too, if the program detects an equals sign
It can combine like terms and like factors easily
it can distribute factors, FOIL them, or expand them according to exponents. (It's not limited to FOIL; it can multiply any number of terms)
There is buggy and limited support for trig functions (sin, cos, tan, cot, sec, csc)
There is the ability to define functions in run-time; though the command-line isn't ready for it yet. (You can manually experiment from int main(), though)
Every function has a domain, and several pieces of domain can be combined to get a whole domain (see code for details)
The classes are organized by file this time
expandable framework

Any questions? I haven't attached an executable yet, but I may in the morning.

Sang-drax
05-16-2003, 12:01 PM
Could you provide a short code example showing how it is used?

ygfperson
05-16-2003, 01:04 PM
after it is compiled, run it, and type in an expression:


9x^2+b

and it will parse it into objects and print it back out again. If there's a way to simplify it, it will do that automatically. ie:


9(x+3)^2

9x^2 + 54x + 81

note: minus signs must have a space after them, otherwise they'll be counted as negative signs

For examples of its use in code, look at int main()
(located in expression.cpp)

Sang-drax
05-16-2003, 02:16 PM
Ahh, I missed the main() function.

These are the changes I had to make to make the code compile in MSVC++.NET:

Added lines to Expression.h


#include <algorithm>
#include <cmath>
using std::sort;
using std::cos;
using std::sin;
using std::tan;
using std::log;
#include <limits>
namespace
{
const double INFINITY = std::numeric_limits<double>::infinity();
}


Added lines to Expression.cpp


const double Float::EPSILON = 0.0000000000001; //double is not an integral type -- inline definition not possible


I also had to add return *this at numerous places where it had been omitted.
At one place (Term::return_first_factor()) I couldn't add "return *this" so I added a throw-statement instead.

Now I'll try the program.

Sang-drax
05-16-2003, 02:30 PM
The simplifying seem to work, I've tested it with some expressions.

If the string "(5)" is entered, the output will not be the same as if "5" is entered, but it could be me not understanding the output.

ygfperson
05-16-2003, 08:40 PM
You're right... I didn't notice that. That's a bug.

Here is the executable:

//edit: another note: make sure there is a '*' between a variable and a parentheses. ie:


f(x)
will be interpreted as the function 'f' with parameter 'x'.

f*(x)
is f * x.

XSquared
05-16-2003, 09:05 PM
It has the wrong output for (x-y)^2

XSquared
05-16-2003, 09:07 PM
Whoops. Nevermind. Forgot about the whole 'space after a minus sign' thing.

vasanth
05-17-2003, 10:23 AM
Can u post the binary please.. could not compile the file

Commander
05-17-2003, 12:15 PM
this is WAYYYYY better then i thought it would be!!!!!

great job man!!

XSquared
05-17-2003, 04:02 PM
Originally posted by vasanth
Can u post the binary please.. could not compile the file
He did at the end of his last post.

Magos
05-17-2003, 04:31 PM
Nice. A few thoughts/bugs:

1) Why is the result printed 4 times? I also noticed that (sometimes) the last two were the 'reverse' of the first two.
Did you use different methods of simplifying the expression, or?

5 + x = 5 + x
5 + x = 5 + x
x + 5 = x + 5
x + 5 = x + 5


2) Sometimes a "+0" or a "*1" is inserted:

Input: (x) = z

x = z
x = z
x + 0 = z
x + 0 = z

Input: f(x) = (f(x + h) - f(x)) / h

f(x) = 1*f([x + h]) + -f(x)*h
f(x) = 1*f([x + h]) + -f(x)*h
f(x) = 0+f([x + h]) + -f(x)*h
f(x) = 0+f([x + h]) + -f(x)*h


Otherwise it seems to work ok.

ygfperson
05-17-2003, 07:48 PM
Originally posted by Magos
Nice.
Thanks.

A few thoughts/bugs:

1) Why is the result printed 4 times? I also noticed that (sometimes) the last two were the 'reverse' of the first two.
Did you use different methods of simplifying the expression, or?
Yes, actually. Sorry for burying int main() in there.
1) Expression after being parsed (unsimplified)
2) Combined like terms and factors
3) Used distributive property to expand factors
4) Evaluated simple functions like trig funcs and logs

That's the gist of it. #4 doesn't work for much of anything more than sin(cos(0)) or sin(3.14) or cot(1)... etc...


2) Sometimes a "+0" or a "*1" is inserted:

Input: (x) = z

x = z
x = z
x + 0 = z
x + 0 = z

Input: f(x) = (f(x + h) - f(x)) / h

f(x) = 1*f([x + h]) + -f(x)*h
f(x) = 1*f([x + h]) + -f(x)*h
f(x) = 0+f([x + h]) + -f(x)*h
f(x) = 0+f([x + h]) + -f(x)*h


Otherwise it seems to work ok.
The '*1' and the '+ 0' are side-effects of the simplification. The function 'clear_extra' should get rid of them, but I haven't put it in int main() because I haven't seen a need to.

BTW, There's a parsing bug I just found out from your output... don't put any whitespace between the '/' and its factors. I'll fix this in the next release so that your input would work.

Sang-drax
05-18-2003, 04:19 AM
Yeah, you should enhance your parser.

x(y+z)
x*-y
(a+b)(c+d)

should be possible

XSquared
05-18-2003, 06:20 AM
x*(y+z)
x*-y works fine.
(a+b)*(c+d)

Sang-drax
05-18-2003, 07:22 AM
Yes, I know those circumventions are possible, but the computer should adapt to the user, not vice verca.
The user should not have to remember to add an extra space after a minus sign.

ygfperson
05-18-2003, 09:53 AM
(a+b)(c+d) does work fine. In some situations the parentheses surrounding the expression don't show when they should, so I'll have to tweak that.

x(a+b) isn't allowed because x() is handled like a function. Graphing calculators have the same problem. The only way I can see to allow that is to differentiate between functions and variables at run-time, which means pre-defining the names of each before using them.

I might be able to tweak minus signs to work correctly in situations. Graphing calculators solve this problem by having a different minus sign than their negative sign. Anyone have any ideas for rules regarding the dash? (ie: if letter before and afterwards, it's a minus sign)

XSquared
05-18-2003, 10:05 AM
Wouldn't it always be possible to interpret it as a negative sign?

4-n = 4+(-n)

ygfperson
05-18-2003, 01:22 PM
Originally posted by XSquared
Wouldn't it always be possible to interpret it as a negative sign?

4-n = 4+(-n)
But that could also be
4-n = 4(-n)

confuted
05-18-2003, 01:59 PM
Most people would probably write that as 4*-n though, or use 4(-n). I don't think anyone would type 4-n and intend 4 times negative n.

edit: impressive program anyway

ygfperson
05-18-2003, 04:34 PM
so... ignoring whitespace, it's a minus sign unless
1) It's preceded by a plus sign
2) it's preceded by a parenthesis
3) it's the first character in the string
4) it's preceded by a '*'

This sound good?

thanks for your input, btw

confuted
05-18-2003, 05:00 PM
That sounds excellent

XSquared
05-18-2003, 08:12 PM
So you can't divide by a negative number, according to your rules...

ygfperson
05-18-2003, 08:44 PM
Originally posted by XSquared
So you can't divide by a negative number, according to your rules...
5) It's preceded by a '/'

BTW, the '/' serves to raise the next factor in the string by -1 power. Negative signs are skipped past, because there's never any intention to divide just by a negative 1.