Log   |   Assignments   |   Source   |   Discussion   |   Feedback   |   About Me  |

This page lists the third revision (v0.2) of the Quadratic Equation Solver.

/*
 * Advanced Computer Architecture
 * Assignment - 1
 * Read the coefficients of a Quadratic equation from the user
 * and calculate the roots using a function call. 
 *
 * Author: Kurian John (CS10M035)
 * Revision History
 * ----------------
 * 2011-02-01 - v0.2
 * 	Almost full rewrite
 * 	 - Better input validation
 * 	 - Handles equations where b*b is much larger
 * 	   than 4*a*c
 * 2011-01-18 - v0.1
 * 	Removed structure return and packed everything into 
 * 	a long double - Read comments for more info
 * 2011-01-05 - v0.0
 * 	New program - Calculate roots of a quadratic
 * 	equation using a function call and return the roots.
 */

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

// Minimum value possible (Anything less than this is considered as 0)
#define EPSILON 1.0E-6

// Prototypes
float solveEquation (float, float, float, unsigned char);
float getInput ();


int main (void)
{
	float a,b,c,p;
	float p1, p2, q;
	char readChar='a', tChar='a';
	printf ("Quadratic Equation Solver\n");
	printf ("-------------------------\n");
	printf ("Please enter the coefficients of the quadratic equation. \nPlease note ");
	printf (" that coefficients should be integers or \nfloating point numbers not exceeding ");
	printf (" eight characters.\n"); 
	while (readChar != 'x')
	{
		printf ("Please enter the coefficient of x^2 (a): ");
		a = getInput ();
		printf ("Please enter the coefficient of x   (b): ");
		b = getInput ();
		printf ("Please enter the constant term      (c): ");
		c = getInput ();

		printf ("Solving %1.6ex^2%+1.6ex%+1.6e=0...\n", a,b,c);
		// Sanity checks
		p = solveEquation (a,b,c, 0);
		switch ((int)p)
		{
			case 0:
				{
					p1 = solveEquation (a,b,c,1);
					p2 = solveEquation (a,b,c,2);
					printf ("The roots are %1.6e and %1.6e.\n", p1, p2);	
					break;
				}
			case 1:
				{
					p = solveEquation (a,b,c,3);
					q = solveEquation (a,b,c, 4);
					printf ("(%1.6e%+1.6ei), (%1.6e%+1.6ei) \n", p, q, p, (-1)*q);
					break;
				}
			case 2:
				{
					printf ("The equation is linear and solution is %1.6e.\n", solveEquation (a,b,c,1) );
					break;
				}
			case 3:
				{
					printf ("The equation is invalid!\n");
				}
		}

		printf ("Enter 'x' to exit. Press return to solve another equation...\n");
		while ( (tChar != 10) && (tChar != 13) ) 
		{
			readChar = tChar;
			tChar = getchar ();
		}
		printf ("\n");
	}

	return 0;
}

/*
 * solveEquation
 * Solves a quadratic equation given the coefficients a, b and c.
 * Returns a float value. The meaning of the return value depeneds
 * on the whatToDo flag
 *   0  : Do sanity checks
 *   1  : First real root / linear solution
 *   2  : Second real root 
 *   3  : Complex root - Real part
 *   4  : Complex root - Imaginary part
 * When called with whatToDo = 0, the return value indicates:
 *   0  : Roots are real
 *   1  : Roots are imaginary
 *   2  : Equation is linear
 *   3  : Equation is invalid
 */
float solveEquation (float a, float b, float c, unsigned char whatToDo)
{
	float discriminant;	
	float p, q;
	switch (whatToDo)
	{
		case 0:
			{
				// If the coefficient of x^2 is 0, solve the linear equation
				//  bx + c = 0 
				if ( fabs (a) < EPSILON)  
				{
					if ( fabs (b) >= EPSILON )
					{
						p = 2; // i = 2 => linear eqn
					}
					// If coefficient of x is also 0, invalid equation
					else
					{
						p = 3; // i = 3 => invalid eqn
					}
				}
				else
				{	
					// Roots are -b/2a + sqrt(discriminant) and 
					// -b/2a - sqrt(discriminant) 
					discriminant = b*b - 4.0*a*c;
					// Roots are imaginary
					if (discriminant < 0.0) 
					{
						p = 1;
					}
					// Roots are real
					else
					{
						p = 0;
					}
				}
				break;

			}
		case 1:
			{
				// If the coefficient of x^2 is 0, solve the linear equation
				//  bx + c = 0 
				if ( fabs (a) < EPSILON)  
				{
					if ( fabs (b) >= EPSILON )
					{
						if (fabs (c) >= EPSILON )
						{
							p=-b / c;
						}
						else
						{
							p=0;
						}
					}
				}
				else
				{	
					// Roots are -b/2a + sqrt(discriminant) and 
					// -b/2a - sqrt(discriminant) 
					discriminant = b*b - 4.0*a*c;
					// Roots are real
					q = sqrt (discriminant);
					if (b > 0)
					{
						p = (b + q) / (-2.0);
					}
					else
					{
						p = (b - q) / (-2.0);
					}
					p = p/a;
				}
				break;
			}
		case 2: // Find the second real root
			{
				discriminant = b*b - 4.0*a*c;

				q = sqrt (discriminant);
				if (b > 0)
				{
					p = (b + q) / (-2.0);
				}
				else
				{
					p = (b - q) / (-2.0);
				}
				p = c / p;
				break;
			}
		case 3: // Find real part of complex solution
			{
				p = b / (-2.0 * a);
				break;
			}
		case 4: // Find imaginary part of complex solution
			{
				discriminant = 4.0*a*c - b*b;
				q = sqrt (discriminant);
				p = q / (2.0 * a);
			}
	}
	return p;			

}

/*
 * Reads the input character by character from the user and does some
 * validation. Ensures that only a float value is returned.
 */
float getInput ()
{
	float retVal;
	unsigned char readChar = 'a', tChar='a', invalidCharFound=0, decimalEntered=0, 
		      commaSkipped=0, currCharInvalid=0, *fullVal, *fullValCorrect;
	int charCount=0, validCharCount=0, entryDone=0;
	fullVal = (unsigned char*) malloc(8);
	fullValCorrect = (unsigned char*) malloc(8);

	while (entryDone == 0)
	{
		while ( (readChar != 10) && (readChar != 13) )
		{
			readChar = getchar();
			if ( (readChar == 10) || (readChar == 13) ) 
			{
				if (charCount == 0)
				{
					printf ("Please enter a value! ");
					readChar = '\0';
					continue;
				}
				else
				{
					break;
				}
			}
			if (!isdigit (readChar) )
			{
				if (
						(((readChar == '-') || (readChar == '+')) && (charCount != 0)) ||
						((readChar == '.') && decimalEntered)
				   )
				{
					invalidCharFound = 1;
					currCharInvalid = 1;
				}
				else if ((readChar == '-') || (readChar == '+'))
				{
					/**/
				}
				else if (readChar == '.')
				{
					decimalEntered = 1;
				}
				else if (readChar == ',')
				{
					if (decimalEntered)
					{
						invalidCharFound = 1;
						currCharInvalid = 1;
					}
					else
					{
						commaSkipped=1;
						continue;
					}
				}
				else
				{
					invalidCharFound = 1;
					currCharInvalid = 1;
				}
			}
			if (!currCharInvalid)
			{
				fullValCorrect = (unsigned char*) realloc (fullValCorrect,(validCharCount+1)*8);
				fullValCorrect[validCharCount] = readChar;
				validCharCount++;
			}
			fullVal = (unsigned char*) realloc (fullVal,(charCount+1)*8);
			fullVal[charCount] = readChar;
			charCount++;
			currCharInvalid = 0;
		}
		fullVal[charCount] = '\0';
		fullValCorrect[validCharCount] = '\0';
		if (commaSkipped) 
			printf ("Warning: Commas (,) in the input were ignored!\n");
		if (strlen ((char*) fullVal) == 0)
		{
			printf ("The input is empty!\n");
			invalidCharFound = 1;
		}
		if (invalidCharFound)	
		{
			printf ("The value that you entered contains invalid characters. Would you like to re-enter (y/n) ? ");
			while ( (tChar != 10) && (tChar != 13) ) 
			{
				readChar = tChar;
				tChar = getchar ();
			}
			// printf ("\n");
			if (readChar == 'n')
			{
				printf ("Not correcting\n");
				entryDone = 1;
			}
			else
			{
				printf ("Correcting\n");
				free (fullVal);
				free (fullValCorrect);
				fullVal = (unsigned char*) malloc(8);
				fullValCorrect = (unsigned char*) malloc(8);
				fullVal[0]='\0';
				fullValCorrect[0]='\0';
				readChar = '\0';
				entryDone = 0;
				charCount = 0;
				validCharCount = 0;
				invalidCharFound = 0;
				currCharInvalid = 0;
				continue;
			}
		}
		entryDone = 1;
	}

	sscanf ((char*) fullValCorrect, "%f", &retVal);

	return retVal;
}