equation solver

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
avansc
Respected Programmer
Respected Programmer
Posts: 1708
Joined: Sun Nov 02, 2008 6:29 pm

equation solver

Post by avansc »

ugly and not clean, just what it is.

wont work if there are white spaces in equation.

h

Code: Select all

/*
 *  cMathExp.h
 *  objects
 *
 *  Created by avansc on 11/6/09.
 *  Copyright 2009 avansc. All rights reserved.
 *
 */

#ifndef _cMathExp_h
#define _cMathExp_h

class cMathExp
{
public:
	cMathExp();
	char *solve(char *data);
	void setPrecision(int x);

private:
	char *pGetExp();
	char *splitInner(char *data);
	char *splitInnerWithBraces(char *data);
	char *replace(const char *subject, const char *search, const char *replace);
	char *trigFunc(char *data, int f);
	int precision;
};

#endif
code

Code: Select all

/*
 *  cMathExp.cpp
 *  objects
 *
 *  Created by avansc on 11/6/09.
 *  Copyright 2009 avansc. All rights reserved.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "cMathExp.h"

cMathExp::cMathExp()
{
	this->precision = -1;
}

void cMathExp::setPrecision(int x)
{
	if(x <= 0)
	{
		this->precision = -1;
	}else if(x <= 10)
	{
		this->precision = x;
	}else{
		this->precision = 10;
	}

}

char *cMathExp::solve(char *data)
{

	printf("%s\n", data);
	
	char *test = (char*)malloc(sizeof(char)*strlen(data));
	test = strdup(data);
	test = strtok(test,  "^*/+-(");
	test = strtok(NULL, "^*/+-(");
	if(!test)
		return data;

	//////////// trig code ///////////
	char *trig[] = {"sin", "cos", "tan", "asin", "acos", "atan"};

	for(int a = 0;a < 6;a++)
	{
		if( (test =strstr(data, trig[a])))
		{
			char *f = (char*)malloc(sizeof(char)*strlen(test));
			f[0] = '\0';
			char *test2 = (char*)malloc(sizeof(char)*strlen(test));
			test2 = strdup(test);
			int count = 0;
			while(*test2)
			{	
				if(*test2 == ')')
				{
					count--;
					if(count == 0)
						break;
				}
				if(count > 0)
				{
					strncat(f, test2, 1);
				}
				if(*test2 == '(')
				{
					count++;
				}
				test2++;
			}
			test2[0] = '\0';
			strncat(test2, test, strlen(f)+5);
			return this->solve(this->replace(data, test2, this->trigFunc(this->solve(f),a)));
		}
	}
	//////////// end trig code ///////////
	
	//////////// braces /////////////
	if(strchr(data, '('))
	{
		return this->solve(this->replace(data,this->splitInnerWithBraces(data), solve(this->splitInner(data))));
	}
	//////////// end braces ///////////
	
	
	/////////// ^,multi,div,add,sub ///////////

	int mdcount = 0;
	char set[] = "1234567890.";
	char signset[] = "^*/+-";
	for(int a = 0;a < strlen(data);a++)
	{
		if(strchr(signset, data[a]))
		{
			mdcount++;
		}
	}
	
	if(mdcount > 1)
	{
		for(int a = 0;a < 5;a++)
		{
			int c1 = 0;
			
			char *numbers = (char*)malloc(sizeof(char)*strlen(data));
			numbers = strdup(data);
			
			char *ops = (char*)malloc(sizeof(char)*strlen(data));
			ops = strdup(data);
			
			ops = strtok(ops, set);
			
			while(ops)
			{
				if(*ops == signset[a])
				{
					char *temp_op = strdup(ops);
					numbers = strtok(numbers, signset);
					for(int b = 0;b < c1;b++)
					{
						numbers = strtok(NULL, signset);
					}
					//printf("%s%s%s\n", numbers, temp_op, strtok(NULL, signset));
					char *t1 = strdup(numbers);
					numbers = strtok(NULL,	signset);
					char *t2 = strdup(numbers);
					strcat(t1, strdup(temp_op));
					strcat(t1, strdup(t2));
					return strdup(this->solve(strdup(this->replace(data, strdup(t1), strdup(this->solve(strdup(t1)))))));;
				}
				ops = strtok(NULL, set);
				c1++;
			}
		}
	}
		
	///////// end multi & div /////////

	char **num = (char**)malloc(sizeof(char*)*2);
	num[0] = (char*)malloc(sizeof(char)*10);
	num[0][0] = '\0';
	
	char op;
	int count = 0;
	
	while(*data)
	{
		if(strchr(set, *data))
		{
			strncat(num[count], data, 1);
		}else {
			count++;
			num[count] = (char*)malloc(sizeof(char)*10);
			num[count][0] = '\0';
			op = *data;
		}

		data++;
	}
	
	float a = atof(num[0]);
	float b = atof(num[1]);
	
	
	float c = 0;
	if(op == '^')
	{
		c = pow(a,b);
	}else if(op == '*')
	{
		c = a * b;
	}else if(op == '/')
	{
		c = a / b;
	}else if(op == '+')
	{
		c = a + b;
	}else if(op == '-')
	{
		c = a - b;
	}
	
	char *alph = (char*)malloc(sizeof(char)*strlen(data)+11);
	sprintf(alph,"%0.10f",(float)c);
	
	alph[strlen(alph)-(10-this->precision)] = '\0'; 
	
	free(num[0]);
	free(num[1]);
	free(num);
	
	return alph;
}	

char *cMathExp::splitInner(char *data)
{
	char *ret = (char*)malloc(sizeof(char)*strlen(data));
	ret[0] = '\0';
	
	while(*data)
	{	
		if(*data == ')')
		{	
			return strdup(ret);
		}
		strncat(ret, data, 1);
		if(*data == '(')
		{	
			ret[0] = '\0';
		}
		data++;
	}
	return NULL;
}

char *cMathExp::splitInnerWithBraces(char *data)
{
	char *ret = (char*)malloc(sizeof(char)*strlen(data));
	ret[0] = '\0';
	
	while(*data)
	{	
		strncat(ret, data, 1);
		if(*data == '(')
		{	
			ret[0] = '\0';
			strncat(ret, data, 1);
		}
		if(*data == ')')
		{	
			return strdup(ret);
		}
		data++;
	}
	return NULL;
}

char *cMathExp::replace(const char *subject, const char *search, const char *replace)
{
		if (search == NULL || replace == NULL || subject == NULL) return NULL;
		if (strlen(search) == 0 || strlen(replace) == 0 || strlen(subject) == 0) return NULL;
		
		char *replaced = (char*)calloc(1, 1), *temp = NULL;
		char *p = (char*)subject, *p3 = (char*)subject, *p2;
		int  found = 0;
		
		while ( (p = strstr(p, search)) != NULL) {
			found = 1;
			temp = (char*)realloc(replaced, strlen(replaced) + (p - p3) + strlen(replace));
			if (temp == NULL) {
				free(replaced);
				return NULL;
			}
			replaced = temp;
			strncat(replaced, p - (p - p3), p - p3);
			strcat(replaced, replace);
			p3 = p + strlen(search);
			p += strlen(search);
			p2 = p;
		}
		
		if (found == 1) {
			if (strlen(p2) > 0) {
				temp = (char*)realloc(replaced, strlen(replaced) + strlen(p2) + 1);
				if (temp == NULL) {
					free(replaced);
					return NULL;
				}
				replaced = temp;
				strcat(replaced, p2);
			}
		} else {
			temp = (char*)realloc(replaced, strlen(subject) + 1);
			if (temp != NULL) {
				replaced = temp;
				strcpy(replaced, subject);
			}
		}
		return replaced;
}

char *cMathExp::trigFunc(char *data, int f)
{
	float a = atof(data);
	
	float c = 0;
	switch(f)
	{
		case 0 :
		{
			c = sin(a);
			break;
		}
		case 1 :
		{
			c = cos(a);
			break;
		}
		case 2 :
		{
			c = tan(a);
			break;
		}
		case 3 :
		{
			c = asin(a);
			break;
		}
		case 4 :
		{
			c = acos(a);
			break;
		}
		case 5 :
		{
			c = atan(a);
			break;
		}
	}
	
	char *alph = (char*)malloc(sizeof(char)*strlen(data));
	sprintf(alph,"%0.10f",(float)c);

	return alph;
}
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: equation solver

Post by short »

I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
avansc
Respected Programmer
Respected Programmer
Posts: 1708
Joined: Sun Nov 02, 2008 6:29 pm

Re: equation solver

Post by avansc »

short wrote:I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!
thanx, yeah its nice.. just note that i have not gone through that to make sure there are no leaks on anything. i dont think there are. but just not that was tinkered with to work, and barely looked at again.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: equation solver

Post by Falco Girgis »

short wrote:I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!
Don't use it too much, though. It fragments your heap to hell when you start having large amounts of small reallocations.
Post Reply