//////////////////////////////////////////////////// // OneWeekGrid.h // // This class implements a 7x24 grid of integers, // // which keeps track of counts foreach hour in a // // one-week period. It also implements an output // // operator to output a formatted version of the // // two-dimensional grid. // //////////////////////////////////////////////////// #ifndef ONE_WEEK_GRID_H #include #include #include #include <iostream> <iomanip> <fstream> <string> using namespace std; const string DAY_OF_WEEK[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY" }; // CLASS DEFINITION // class OneWeekGrid { public: OneWeekGrid(); OneWeekGrid(const OneWeekGrid &grid); void addItem(string day, string militaryTime); int maxItem() const; friend ostream& operator << (ostream &outputFile, const OneWeekGrid &grid); private: int itemCount[7][24]; }; // CLASS IMPLEMENTATION // // Default Constructor: Initializes the grid elements to zero. OneWeekGrid::OneWeekGrid() { int weekday; int hour; for (weekday = 0; weekday < 7; weekday++) for (hour = 0; hour < 24; hour++) itemCount[weekday][hour] = 0; } // Copy Constructor: Duplicates the parameterized OneWeekGrid. OneWeekGrid::OneWeekGrid(const OneWeekGrid &grid) { int weekday; int hour; for (weekday = 0; weekday < 7; weekday++) for (hour = 0; hour < 24; hour++) itemCount[weekday][hour] = grid.itemCount[weekday][hour]; // Member Function addItem: Increments the count for the grid element corresponding to the // day parameter (a string representing a day - "Sunday", "Monday", etc. - which is converted // into the appropriate row number - 0, 1, etc.) and the militaryTime parameter (which is // converted from a string, such as "1530", into the corresponding column number, such as 15). void OneWeekGrid::addItem(string day, string militaryTime) { int dayNumber; int hour = 10 * ( int(militaryTime[0]) - int('0') ) + ( int(militaryTime[1]) - int('0') ); switch (day[0]) { case 'S': { dayNumber = (day.length() == 6) ? 0 : 6; break; } case 'M': { dayNumber = 1; break; } case 'T': { dayNumber = (day.length() == 7) ? 2 : 4; break; } case 'W': { dayNumber = 3; break; } case 'F': { dayNumber = 5; break; } default : return; } itemCount[dayNumber][hour]++; return; } // Member function maxItem: Returns the largest value in the grid. int OneWeekGrid::maxItem() const { int maxValue = 0; int weekday; int hour; for (weekday = 0; weekday < 7; weekday++) for (hour = 0; hour < 24; hour++) if (itemCount[weekday][hour] > maxValue) maxValue = itemCount[weekday][hour]; return maxValue; } // Output Operator: Outputs the grid, with standardized widths for each value (to // facilitate lining the columns up), spaces between consecutive row elements, and // line feeds separating consecutive rows. ostream& operator << (ostream &outputFile, const OneWeekGrid &grid) { int weekday, hour, digitIndex; int maxVal = grid.maxItem(); int nbrDigits = 0; while (maxVal > 0) { nbrDigits++; maxVal /= 10; } if (nbrDigits < 2) nbrDigits = 2; outputFile << setw(11) << " "; for (hour = 0; hour < 24; hour++) outputFile << setw(nbrDigits) << hour << " "; outputFile << endl << setw(11) << " "; for (hour = 0; hour < 24; hour++) { for (digitIndex = 1; digitIndex <= nbrDigits; digitIndex++) outputFile << '-'; outputFile << " "; } outputFile << endl; for (weekday = 0; weekday < 7; weekday++) { outputFile << setw(9) << DAY_OF_WEEK[weekday] << ": "; for (hour = 0; hour < 24; hour++) outputFile << setw(nbrDigits) << grid.itemCount[weekday][hour] << " "; outputFile << endl; } return outputFile; } #define ONE_WEEK_GRID_H #endif ////////////////////////////////////////////////////// // This program uses the oneWeekGrid class to input // // a full week's data from a user-specified file, // // counting every occurrence of every hour in every // // day that occurs in the file. It then outputs the // // result to a user-specified output file. // ////////////////////////////////////////////////////// #include #include #include #include <iostream> <fstream> <string> "OneWeekGrid.h" using namespace std; void loadGrid(OneWeekGrid &grid, ifstream &file); // The main function queries the user for the file names, opens // the files, loads and outputs the grid, and closes the files. void main() { OneWeekGrid weekGrid; string inputFileName, outputFileName; ifstream inputFile; ofstream outputFile; cout << "Specify the name of the input file containing the day/time data: "; cin >> inputFileName; inputFile.open(inputFileName.c_str()); cout << endl << endl; loadGrid(weekGrid, inputFile); inputFile.close(); cout << "Specify the name of the output file to contain the week's hourly data: "; cin >> outputFileName; outputFile.open(outputFileName.c_str()); cout << endl << endl; outputFile << weekGrid; outputFile.close(); return; } // The loadGrid function repeatedly retrieves day/time string // pairs from the input file and updates the grid acccordingly. void loadGrid(OneWeekGrid &grid, ifstream &file) { string dayOfWeek; string timeOfDay; file >> dayOfWeek; while (!file.eof()) { file >> timeOfDay; grid.addItem(dayOfWeek, timeOfDay); file >> dayOfWeek; } return; } Tuesday Thursday Saturday Friday Sunday Thursday Sunday Sunday Saturday Monday Wednesday Monday Wednesday Friday Monday Saturday Wednesday Tuesday Monday Monday Wednesday Monday Monday Thursday Friday SUNDAY: MONDAY: TUESDAY: WEDNESDAY: THURSDAY: FRIDAY: SATURDAY: 2100 1116 0159 1339 1602 0156 0446 1816 0829 1414 0414 0310 2001 1201 1008 1830 1911 1921 2055 2354 1640 2359 0603 0801 1557 0 --112 123 111 138 118 129 106 Saturday Friday Friday Tuesday Monday Sunday Sunday Friday Saturday Saturday Sunday Monday Tuesday Monday Saturday Saturday Tuesday Sunday Wednesday Monday Sunday Thursday Monday Thursday Tuesday 1 --139 118 132 134 126 138 128 2 --121 131 134 117 127 117 116 3 --127 131 113 121 111 127 113 1336 0718 0803 0111 1138 0118 1317 1916 1032 0632 1458 1957 2131 0237 1308 1536 1516 1715 0150 0823 1717 0549 0340 0759 1532 4 --126 105 128 91 124 116 114 Saturday Sunday Wednesday Tuesday Thursday Wednesday Sunday Thursday Sunday Tuesday Thursday Thursday Thursday Saturday Sunday Tuesday Thursday Sunday Tuesday Thursday Saturday Friday Thursday Saturday Tuesday 5 --105 102 108 123 111 105 119 6 --104 129 141 118 121 114 120 7 --119 109 119 125 116 126 110 1021 1039 0705 1016 0806 0823 1427 2256 1734 1316 0645 0737 0321 0503 1118 1300 2010 2301 0431 0210 1928 0628 1606 1711 2119 8 --116 134 108 104 135 126 111 Monday Thursday Sunday Tuesday Saturday Wednesday Sunday Saturday Monday Wednesday Sunday Tuesday Wednesday Friday Saturday Monday Wednesday Wednesday Sunday Tuesday Saturday Friday Friday Friday Thursday 9 --124 116 122 142 134 145 138 10 --113 124 115 130 110 110 138 11 --132 116 106 130 90 110 105 1342 0601 1053 0945 0305 0704 1110 0541 0520 0636 1406 1612 0700 1501 0633 0330 0943 1129 0436 1731 1500 1325 1631 1311 1850 12 --119 116 126 101 113 120 122 Saturday Monday Tuesday Thursday Monday Friday Monday Saturday Saturday Saturday Wednesday Saturday Sunday Friday Saturday Saturday Tuesday Sunday Saturday Tuesday Thursday Thursday Wednesday Thursday 13 Tuesday 14 15 --118 111 118 137 120 117 130 --116 118 127 120 143 125 101 --105 124 117 120 100 127 126 0116 1331 1125 0010 0439 2128 1342 2109 2144 1709 0741 0157 1744 1025 0212 1719 2303 1708 2047 1326 1839 2056 1443 0907 16 17 0634 --117 127 117 128 127 133 108 --124 133 125 121 109 121 133 18 --117 111 90 124 126 118 111 19 --108 126 103 125 108 130 133 Friday 1905 Friday 0404 Thursday 2038 Wednesday 0419 Tuesday 1325 Monday 0537 Tuesday 1708 Monday 1503 Monday 2200 Wednesday 2126 Tuesday 2221 Thursday 2048 Monday 1910 Wednesday 0032 Monday 0823 Thursday 2305 Sunday 2216 Saturday 2029 Friday 0800 Monday 0841 Tuesday 0834 Monday 0407 20 21 22 23 Monday --- --- ---0439 --Tuesday 140 112 1130737 113 Wednesday 128 123 1051902 110 130 117 118 105 133 108 111 126 113 93 97 114 107 108 92 102 136 132 127 107 // SquareMatrix.h // The SquareMatrix class implements a square matrix of double // values, with functionality to add, subtract, multiply (both // scalar and matrix multiplication), invert, input, and output. #ifndef SQUARE_MATRIX_H #include <fstream> #include <iomanip> using namespace std; // // // // const int MAX_SIZE = 10; // CLASS DEFINITION class SquareMatrix { public: SquareMatrix(); SquareMatrix(int matrixSize); SquareMatrix(const SquareMatrix &sm); int getSize(); SquareMatrix invert(); double operator () (int row, int column); friend SquareMatrix operator + (const SquareMatrix &smA, const SquareMatrix &smB); friend SquareMatrix operator - (const SquareMatrix &smA, const SquareMatrix &smB); friend SquareMatrix operator * (const SquareMatrix &smA, const SquareMatrix &smB); friend SquareMatrix operator * (double coefficient, const SquareMatrix &sm); friend ostream& operator << (ostream &outputFile, const SquareMatrix &sm); friend istream& operator >> (istream &inputFile, SquareMatrix &sm); private: int size; double matrix[MAX_SIZE][MAX_SIZE]; }; // CLASS IMPLEMENTATION // Default Constructor: Initializes // the SquareMatrix to an identity // matrix of the maximum size. SquareMatrix::SquareMatrix() { int row, col; size = MAX_SIZE; for (row = 0; row < MAX_SIZE; row++) for (col = 0; col < MAX_SIZE; col++) if (row == column) matrix[row][col] = 1.0; else matrix[row][col] = 0.0; return; } //Initializing Constructor: Initializes // the SquareMatrix the an identity // matrix of the parameterized size. SquareMatrix::SquareMatrix(int matrixSize) { int row, col; size = matrixSize; for (row = 0; row < matrixSize; row++) for (col = 0; col < matrixSize; col++) if (row == col) matrix[row][col] = 1.0; else matrix[row][col] = 0.0; return; } // Copy Constructor: Copies the // parameterized SquareMatrix. SquareMatrix::SquareMatrix(const SquareMatrix &sm) { int row, col; size = sm.size; for (row = 0; row < size; row++) for (col = 0; col < size; col++) matrix[row][col] = sm.matrix[row][col]; return; } // Size Accessor Function: Merely // returns the SquareMatrix size value. int SquareMatrix::getSize() { return size; } // Invert Member Function: By applying the same operations to an identity matrix as to // the original matrix, placing the latter in reduced row echelon form results in // transforming the former into the inverse matrix of the original matrix. SquareMatrix SquareMatrix::invert() { int row, column, index; double temp, scaleFactor; SquareMatrix copyMatrix(size); SquareMatrix inverseMatrix(size); for (row = 0; row < size; row++) for (column = 0; column < size; column++) copyMatrix.matrix[row][column] = matrix[row][column]; // Convert the original matrix to reduced row echelon form, performing // the same operations on what will become the inverse matrix. for (row = 0; row < size; row++) { // If this diagonal element is zero, swap rows with // one in which this column's value is not zero. if (copyMatrix.matrix[row][row] == 0.0) { index = row + 1; while (copyMatrix.matrix[index][row] == 0.0) index++; for (column = 0; column < size; column++) { temp = copyMatrix.matrix[row][column]; copyMatrix.matrix[row][column] = copyMatrix.matrix[index][column]; copyMatrix.matrix[index][column] = temp; temp = inverseMatrix.matrix[row][column]; inverseMatrix.matrix[row][column] = inverseMatrix.matrix[index][column]; inverseMatrix.matrix[index][column] = temp; } } // Scale the row so its diagonal element is one. scaleFactor = copyMatrix.matrix[row][row]; for (column = 0; column < size; column++) { copyMatrix.matrix[row][column] /= scaleFactor; inverseMatrix.matrix[row][column] /= scaleFactor; } // Subtract a scaled version of the row from all // other rows until the only non-zero element in // the column is the one in the row's diagonal slot. for (index = 0; index < size; index++) if ( (index != row) && (copyMatrix.matrix[index][row] != 0.0) ) { scaleFactor = copyMatrix.matrix[index][row]; for (column = 0; column < size; column++) { copyMatrix.matrix[index][column] -= copyMatrix.matrix[row][column] * scaleFactor; inverseMatrix.matrix[index][column] -= inverseMatrix.matrix[row][column] * scaleFactor; } } } return inverseMatrix; } // Overloaded Parentheses Operator: Returns the matrix value at the slot corresponding // to the parameterized indices. (Returns zero if those indices are invalid.) double SquareMatrix::operator () (int row, int column) { if ( (row >= 0) && (row < size) && (column >= 0) && (column < size) ) return matrix[row][column]; else return 0.0; } // Overloaded Addition Operator: Returns a SquareMatrix that is the sum of the two SquareMatrix // parameter values (using the smaller of their two sizes if they differ in size). SquareMatrix operator + (const SquareMatrix &smA, const SquareMatrix &smB) { SquareMatrix newMatrix; int row, column; newMatrix.size = (smA.size < smB.size) ? smA.size : smB.size; for (row = 0; row < newMatrix.size; row++) for (column = 0; column < newMatrix.size; column++) newMatrix.matrix[row][column] = smA.matrix[row][column] + smB.matrix[row][column]; return newMatrix; } // Overloaded Subtraction Operator: Returns a SquareMatrix thatis the difference of the two // SquareMatrix parameter values (using the smaller of their two sizes if they differ in size). SquareMatrix operator - (const SquareMatrix &smA, const SquareMatrix &smB) { SquareMatrix newMatrix; int row, column; newMatrix.size = (smA.size < smB.size) ? smA.size : smB.size; for (row = 0; row < newMatrix.size; row++) for (column = 0; column < newMatrix.size; column++) newMatrix.matrix[row][column] = smA.matrix[row][column] - smB.matrix[row][column]; return newMatrix; } // Overloaded Multiplication Operator: Returns a SquareMatrix that // is the product of the two parameterized SquareMatrix values // (using the smaller of their two sizes if they differ in size). SquareMatrix operator * (const SquareMatrix &smA, const SquareMatrix &smB) { SquareMatrix newMatrix; int row, column, index; newMatrix.size = (smA.size < smB.size) ? smA.size : smB.size; for (row = 0; row < newMatrix.size; row++) for (column = 0; column < newMatrix.size; column++) { newMatrix.matrix[row][column] = 0.0; for (index = 0; index < newMatrix.size; index++) newMatrix.matrix[row][column] += smA.matrix[row][index] * smB.matrix[index][column]; } return newMatrix; } // Overloaded Multiplication Operator: Returns a SquareMatrix // that is the product of the parameterized scalar value and // the parameterized SquareMatrix value. SquareMatrix operator * (double coefficient, const SquareMatrix &sm) { SquareMatrix newMatrix; int row, column; newMatrix.size = sm.size; for (row = 0; row < newMatrix.size; row++) for (column = 0; column < newMatrix.size; column++) newMatrix.matrix[row][column] = coefficient * sm.matrix[row][column]; return newMatrix; } // Overloaded Output Operator: Outputs the parameterized SquareMatrix // to the parameterized output file, using 10 digits for each value // in the matrix and inserting a linefeed after each row. ostream& operator << (ostream &outputFile, const SquareMatrix &sm) { int row, column; outputFile.setf(ios::fixed); outputFile.setf(ios::showpoint); outputFile.precision(3); for (row = 0; row < sm.size; row++) { for (column = 0; column < sm.size; column++) outputFile << setw(10) << sm.matrix[row][column]; outputFile << endl; } return outputFile; } // Overloaded Input Operator: Inputs the parameterized SquareMatrix // from the parameterized input file, reading the elements of one // row at a time. istream& operator >> (istream &inputFile, SquareMatrix &sm) { int row, column; inputFile >> sm.size; for (row = 0; row < sm.size; row++) for (column = 0; column < sm.size; column++) inputFile >> sm.matrix[row][column]; return inputFile; } #define SQUARE_MATRIX_H #endif // This driver program merely tests the SquareMatrix class functionality. #include <iostream> #include <fstream> #include "SquareMatrix.h" using namespace std; void main() { SquareMatrix matA, matB, invA; ifstream sourceFile1, sourceFile2; ofstream destinationFile; int i; sourceFile1.open("MatrixData1.txt"); sourceFile1 >> matA; sourceFile1.close(); sourceFile2.open("MatrixData2.txt"); sourceFile2 >> matB; sourceFile2.close(); destinationFile.open("MatrixResults.txt"); destinationFile << "MATRIX A:" << endl << matA << endl; destinationFile << "MATRIX B:" << endl << matB << endl; destinationFile << "DIAGONAL OF B: "; for (i = 0; i < matB.getSize(); i++) destinationFile << matB(i, i) << " "; destinationFile << endl << endl; destinationFile << "SUM (A+B):" << endl << matA + matB << endl; destinationFile << "DIFFERENCE (A-B):" << endl << matA - matB << endl; destinationFile << "MATRIX PRODUCT (A*B):" << endl << matA * matB << endl; destinationFile << "SCALAR PRODUCT (5*B):" << endl << 5 * matB << endl; invA = matA.invert(); destinationFile << "INVERSE OF A:" << endl << invA << endl; destinationFile << "PRODUCT OF A AND ITS INVERSE:" << endl << matA * invA << endl; destinationFile.close(); return; } 4 3.5 2.4 1.0 -4.6 -1.7 0.0 4.7 2.1 6.6 4.8 -5.0 1.6 2.1 -8.5 3.5 -7.4 4 -6.4 1.2 6.1 -4.7 0.1 7.4 -0.5 5.3 4.2 0.0 8.4 -8.5 5.3 -7.1 6.6 1.2 MATRIX A: 3.500 -1.700 6.600 2.100 2.400 0.000 4.800 -8.500 1.000 4.700 -5.000 3.500 -4.600 2.100 1.600 -7.400 MATRIX B: -6.400 0.100 4.200 5.300 1.200 7.400 0.000 -7.100 6.100 -0.500 8.400 6.600 -4.700 5.300 -8.500 1.200 DIAGONAL OF B: -6.400 SUM (A+B): -2.900 -1.600 10.800 7.400 7.400 8.400 1.200 3.600 7.400 4.800 -15.600 7.100 4.200 3.400 10.100 -9.300 7.400 -6.900 -6.200 DIFFERENCE (A-B): 9.900 1.200 -1.800 -7.400 2.400 4.800 -3.200 -1.400 -5.100 5.200 -13.400 -3.100 0.100 -3.200 10.100 -8.600 MATRIX PRODUCT (A*B): -42.340 54.620 41.750 -16.950 -54.280 32.080 -38.810 -7.840 -1.810 42.970 6.420 -2.380 -17.750 -29.440 38.840 -93.550 SCALAR PRODUCT (5*B): -32.000 6.000 0.500 37.000 21.000 0.000 26.500 -35.500 30.500 -2.500 42.000 33.000 -23.500 26.500 -42.500 6.000 INVERSE OF A: -0.027 0.120 0.147 -0.004 0.057 0.197 -0.149 0.132 0.169 -0.046 0.013 0.107 0.088 -0.102 0.023 0.018 PRODUCT OF A AND ITS INVERSE: 1.000 0.000 0.000 0.000 1.000 -0.000 -0.000 0.000 1.000 0.000 -0.000 -0.000 0.000 -0.000 -0.000 1.000 #include <iostream> #include <fstream> #include <string> using namespace std; const int NBR_SEQUENCES = 6; const char SEQUENCE[] = { '\a', '\n', '\t', '\\', '\'', '\"' }; const string SEQUENCE_LABEL[] = { "ALERT (\\a): ", "NEW LINE (\\n): ", "HORIZONTAL TAB (\\t): ", "BACKSLASH (\\\\): ", "SINGLE QUOTATION MARK (\\'): ", "DOUBLE QUOTATION MARK (\\\"): " }; void printHeader(); void outputSequence(int index); void main() { int i; printHeader(); for (i = 0; i < NBR_SEQUENCES; i++) outputSequence(i); } void printHeader() { cout << " ESCAPE SEQUENCE TESTER" << endl; cout << " ----------------------" << endl; cout << "This application tests each of the C++ escape" cout << "sequences by verifying that you are ready for" cout << "the next one, and then using it in output six" cout << "times, with every time preceded by an ordinal" cout << "number (1 through 6). " << endl << endl; } void outputSequence(int index) { char whatever; int i; cout << "Enter any character to proceed " << "to the next escape sequence: "; cin >> whatever; cout << endl << SEQUENCE_LABEL[index] << endl; for (i = 1; i <= 6; i++) cout << i << SEQUENCE[index]; cout << "(end of sequence)" << endl << endl << endl; } << << << << endl; endl; endl; endl; #include #include #include #include <iostream> <iomanip> <fstream> <string> using namespace std; const string INPUT_FILE_NAME = "Source.txt"; const string LEFT_OUTPUT_FILE_NAME = "LeftOutput.txt"; const string RIGHT_OUTPUT_FILE_NAME = "RightOutput.txt"; int getInputSize(); void loadArray(double list[], int listSize); void leftFormatOutput(double list[], int listSize); void rightFormatOutput(double list[], int listSize); void outputArray(ofstream &file, double list[], int listSize); void main() { double* nbrList; int size; size = getInputSize(); nbrList = new double[size]; loadArray(nbrList, size); leftFormatOutput(nbrList, size); rightFormatOutput(nbrList, size); delete[] nbrList; return; } int getInputSize() { int count = 0; double value; ifstream sourceFile; sourceFile.open(INPUT_FILE_NAME.c_str()); sourceFile >> value; while (!sourceFile.eof()) { count++; sourceFile >> value; } sourceFile.close(); return count; } void leftFormatOutput(double list[], int listSize) { ofstream outputFile; outputFile.open(LEFT_OUTPUT_FILE_NAME.c_str()); outputFile.setf(ios::left); outputFile.setf(ios::fixed); outputFile.setf(ios::showpoint); outputFile.precision(4); outputArray(outputFile, list, listSize); outputFile.close(); return; } void loadArray(double list[], int listSize) { int index; ifstream inputFile; void rightFormatOutput(double list[], int listSize) inputFile.open(INPUT_FILE_NAME.c_str()); for (index = 0; index < listSize; index++) { ofstream outputFile; inputFile >> list[index]; outputFile.open(RIGHT_OUTPUT_FILE_NAME.c_str()); inputFile.close(); outputFile.setf(ios::right); return; outputFile.setf(ios::fixed); } outputFile.setf(ios::showpoint); outputFile.precision(2); outputArray(outputFile, list, listSize); outputFile.close(); return; } void outputArray(ofstream &file, double list[], int listSize) { int index; file << setw(10) << "COLUMN 1" << setw(10) << "COLUMN 2" << setw(10) << "COLUMN 3" << endl; for (index = 0; index < listSize; index++) { file << setw(10) << list[index]; if (index % 3 == 2) file << endl; } return; } 3.14159 98.6 2.71828 0.5772156649 1.61803398874989 6.02214199 -2.0023193 -3.82608545 -273.15 COLUMN 1 3.1416 0.5772 -2.0023 COLUMN 2 98.6000 1.6180 -3.8261 COLUMN 1 3.14 0.58 -2.00 COLUMN 3 2.7183 6.0221 -273.1500 COLUMN 2 98.60 1.62 -3.83 COLUMN 3 2.72 6.02 -273.15 (x0, f(x0) x0 (First Guess) x1 = x0 – f(x0)/f(x0) x2 = x 1 – f(x1)/f(x1) (x1, f(x1) //////////////////////////////////////////////////////////////////////// // Polynomial.h - Poloynomial Class Definition // // Uses a dynamic array to store the coefficients of a polynomial. // // Includes member functions for taking the derivative and evaluating // // at specific x-values, as well as a friend output operator. // //////////////////////////////////////////////////////////////////////// #ifndef POLYNOMIAL_H #include <iostream> #include <fstream> using namespace std; // THE CLASS DEFINITION // class Polynomial { public: Polynomial(); Polynomial(int deg); Polynomial(const Polynomial &poly); void setDegree(int exponent); void setCoefficient(int exponent, double coeff); Polynomial derivative() const; double evaluateAt(double x) const; friend ostream& operator << (ostream &outputFile, const Polynomial &poly); private: int degree; double* coefficient; }; // THE CLASS IMPLEMENTATION // // Default Constructor: Sets Polynomial's // degree to meaningless negative value. Polynomial::Polynomial() { degree = -1; } // Initializing Constructor: Sets Polynomial's // degree to parameterized value, resetting all // coefficients to zero. Polynomial::Polynomial(int deg) { degree = deg; if (degree >= 0) coefficient = new double[degree + 1]; } // Copy Constructor: Duplicates parameterized Polynomial. Polynomial::Polynomial(const Polynomial &poly) { int exponent; degree = poly.degree; if (degree >= 0) { coefficient = new double[degree + 1]; for (exponent = 0; exponent <= degree; exponent++) coefficient[exponent] = poly.coefficient[exponent]; } } // Mutator Function setDegree: Resets Polynomial's degree, // resetting all coefficients to zero at the same time. void Polynomial::setDegree(int exponent) { int power; if (degree >= 0) delete[] coefficient; degree = exponent; if (exponent >= 0) { coefficient = new double[degree + 1]; for (power = 0; power <= degree; power++) coefficient[power] = 0.0; } return; } // Mutator Function setCoefficient: Resets the coefficient of // the Polynomial's term with the parameterized exponent to the // parameterized value (if possible). void Polynomial::setCoefficient(int exponent, double coeff) { if ( (exponent >= 0) && (exponent <= degree) ) coefficient[exponent] = coeff; return; } // Member Function derivative: Generates new Polynomial that // is the derivative function for the existing Polynomial. Polynomial Polynomial::derivative() const { Polynomial derivPoly; int power; // If the Polynomial is meaningless, so is its derivative. if (degree < 0) derivPoly.setDegree(-1); // If the Polynomial is constant, its derivative is zero. else if (degree == 0) { derivPoly.setDegree(0); derivPoly.setCoefficient(0, 0.0); } // If the Polynomial is "regular", differentiate in the normal way. else { derivPoly.setDegree(degree - 1); for (power = 1; power <= degree; power++) derivPoly.setCoefficient(power - 1, power * coefficient[power]); } return derivPoly; } // Member Function evaluateAt: Calculates and returns the // Polynomial's value at the parameterized x-value (if possible). double Polynomial::evaluateAt(double x) const { double result = 0.0; int power; if (degree >= 0) { result = coefficient[degree]; for (power = degree - 1; power >= 0; power--) result = result * x + coefficient[power]; } return result; } // Output Operator: Outputs the parameterized Polynomial (in standard // polynomial format) to the parameterized output file. ostream& operator << (ostream &outputFile, const Polynomial &poly) { int power; // Only output if the Polynomial is meaningful. if (poly.degree >= 0) { // Skip all of the leading terms with zero coefficients. power = poly.degree; while ( (poly.coefficient[power] == 0.0) && (power > 0) ) power--; // Output the leading term and its coefficient properly. if (poly.coefficient[power] == -1.0) outputFile << "-"; else if (poly.coefficient[power] != 1.0) outputFile << poly.coefficient[power]; if (power == 1) outputFile << "x"; else if (power > 1) outputFile << "x^" << power; // Cycle through the rest of the polynomial's terms. power--; while (power >= 0) { // Skip all terms with zero coefficients. if (poly.coefficient[power] != 0.0) { // Handle positive and negative coefficients // as sums and differences. if (poly.coefficient[power] < 0.0) { outputFile << " - "; if (poly.coefficient[power] != -1.0) outputFile << -poly.coefficient[power]; } else { outputFile << " + "; if ( (poly.coefficient[power] != 1.0) || (power == 0) ) outputFile << poly.coefficient[power]; } if (power == 1) outputFile << "x"; else if (power > 1) outputFile << "x^" << power; } power--; } } return outputFile; } #define POLYNOMIAL_H #endif ///////////////////////////////////////////////////////////////////// // NewtonsMethod.cpp - Driver Program To Implement Newton's Method // // this driver program employs the Polynomial class to query the // // user for a polynomial (its degree and coefficients) and a guess // // of a possible root. It then uses Newton's Method to iteratively // // locate an actual root for the polynomial (if possible). // ///////////////////////////////////////////////////////////////////// #include <iostream> #include <cmath> #include "Polynomial.h" using namespace std; Polynomial retrievePolynomial(); double retrieveRootGuess(const Polynomial &poly); void outputNewtonsResults(const Polynomial &poly, double currentX); // The main function sets the output format, and then supervises the // retrieval of the polynomial and the user's root guess, followed by // the application of Newton's Method to approximate an actual root. void main() { Polynomial poly; double currentXGuess; cout.setf(ios::fixed); cout.precision(3); poly = retrievePolynomial(); currentXGuess = retrieveRootGuess(poly); outputNewtonsResults(poly, currentXGuess); } // The retrievePolynomial queries the user for polynomial information // (the degree and coefficients of the polynomial). Polynomial retrievePolynomial() { Polynomial poly; int exponent; int powerIndex; double coeff; cout << "Specify the degree of the polynomial's leading coefficient: "; cin >> exponent; while (exponent < 0.0) { cout << "Negative degrees are unacceptable. Please try again: "; cin >> exponent; } poly.setDegree(exponent); for (powerIndex = exponent; powerIndex >= 0; powerIndex--) { cout << "Specify the coefficient of the "; switch (powerIndex) { case 0: cout << "constant"; break; case 1: cout << "linear"; break; case 2: cout << "quadratic"; break; case 3: cout << "cubic"; break; default: cout << "x^" << powerIndex; break; } cout << " term: "; cin >> coeff; poly.setCoefficient(powerIndex, coeff); } return poly; } // Function retrieveRootGuess queries the user for an initial // estimate of a root for the parameterized polynomial. double retrieveRootGuess(const Polynomial &poly) { double possibleRoot; cout << "Specify a first \"guess\" at a root for the polynomial" << endl << "f(x) = " << poly << " : "; cin >> possibleRoot; return possibleRoot; } // The outputNewtonsResults function runs Newton's Method on the parameterized // polynomial, starting at the parameterized x-value, and outputs the ordered // pairs of values that occur until either the sequence converges (i.e., the // current x-value produces a near-zero y-value) or it diverges (i.e., // consecutive x-values start getting further and further apart). void outputNewtonsResults(const Polynomial &poly, double currentX) { const double EPSILON = 0.000001; Polynomial derivPoly = poly.derivative(); double currentY = poly.evaluateAt(currentX); double previousX; double derivY; double previousError = 100000.0; double currentError; bool acceptableError = true; bool converged = false; // Keep iterating as long as the current x-value doesn't // produce a y-value adequately close to zero, or until // consecutive x-values start getting further apart. while ( (acceptableError) && (!converged) ) { cout << "x = " << currentX << " f(x) = " << currentY << endl; derivY = derivPoly.evaluateAt(currentX); // Newton's Method requires dividing by the derivative, so if // the derivative equals zero, conclude that the method failed. if (derivY == 0.0) acceptableError = false; else { previousX = currentX; currentX -= currentY / derivY; currentY = poly.evaluateAt(currentX); converged = (fabs(currentY) < EPSILON); currentError = fabs(currentX - previousX); acceptableError = (currentError < previousError); previousError = currentError; } } // // // if If the iterative process terminates due to convergence, then the approximate root is output. Otherwise, the failure of the method is reported. (converged) cout << endl << "Newton's Method estimates a root for the polynomial" << endl << "f(x) = " << poly << " at x = " << currentX << endl << endl; else cout << "Newton's Method failed for this polynomial and this initial guess. " << endl << endl; return; } //////////////////////////////////////////////////// // Statistics.h // // Contains various statistics utility functions. // //////////////////////////////////////////////////// #ifndef STATISTICS_H #include <cmath> // The minimum function returns the smallest value in the parameterized array. double minimum(const double val[], int size) { double minVal = val[0]; int index; for (index = 1; index < size; index++) if (val[index] < minVal) minVal = val[index]; return minVal; } // The maximum function returns the largest value in the parameterized array. double maximum(const double val[], int size) { double maxVal = val[0]; int index; for (index = 1; index < size; index++) if (val[index] > maxVal) maxVal = val[index]; return maxVal; } // The mean function returns the average of all // values in the parameterized array. double mean(const double list[], int size) { int index; double sum = 0.0; for (index = 0; index < size; index++) sum += list[index]; if (size == 0) return 0.0; else return sum / size; } // The standardDeviation function returns the standard // deviation of all values in the parameterized array. double standardDeviation(const double list[], int size) { double average = mean(list, size); double sumSquareDiff = 0.0; int index; for (index = 0; index < size; index++) sumSquareDiff += pow( (list[index] - average), 2 ); if (size == 0) return 0.0; else return sqrt( sumSquareDiff / size ); } // The linearRegression function calculates the slope and y-intercept // of the line that most closely approximates (via the least-squares // approach) the set of points represented by the two parallel arrays. void linearRegression(const double x[], const double y[], int size, double &slope, double &yIntercept) { double averageX = mean(x, size); double averageY = mean(y, size); double numerator = 0; double denominator = 0; int index; for (index = 0; index < size; index++) { numerator += (x[index] - averageX) * (y[index] - averageY); denominator += pow( (x[index] - averageX), 2 ); } if (denominator == 0.0) slope = 0.0; else slope = numerator / denominator; yIntercept = averageY - slope * averageX; return; } #define STATISTICS_H #endif ////////////////////////////////////////////////////////////////////////////////// // ImageGrid.h // // This header file includes the definition and implementation of the ImageGrid // // class, which represents a two-dimensional image composed of characters. // ////////////////////////////////////////////////////////////////////////////////// #ifndef IMAGE_GRID_H #include <iostream> #include <fstream> #include <string> using namespace std; const int GRID_SIZE = 50; // THE CLASS DEFINITION // class ImageGrid { public: ImageGrid(); void xyToRowColumn(double x, double y, int &row, int &column); void initializeGrid(double xMin, double xMax, double yMin, double yMax); void markGrid(double x, double y, char symbol); void drawLine(double slope, double intercept, char symbol); friend ostream& operator << (ostream &outputFile, const ImageGrid &image); private: char grid[GRID_SIZE][GRID_SIZE]; double lowerBoundX; double upperBoundX; double lowerBoundY; double upperBoundY; }; // THE CLASS IMPLEMENTATION // // Default Constructor - Initializes grid to all blanks. // ImageGrid::ImageGrid() { int row, column; for (row = 0; row < GRID_SIZE; row++) for (column = 0; column < GRID_SIZE; column++) grid[row][column] = ' '; } // Member function xyToRowColumn: Determines // the grid's row/column pair that corresponds // to the parameterized x- and y-coordinates. void ImageGrid::xyToRowColumn(double x, double y, int &row, int &column) { column = int( (x - lowerBoundX) * (GRID_SIZE - 1) / (upperBoundX - lowerBoundX) ); row = int( (upperBoundY - y) * (GRID_SIZE -1) / (upperBoundY - lowerBoundY) ); return; } // Member function initializaGrid: Uses the parameterized x- and y-coordinate limits // to determine where in the image the coordinate axes should be placed. void ImageGrid::initializeGrid(double xMin, double xMax, double yMin, double yMax) { int zeroRow, zeroColumn, row, column; lowerBoundX = xMin; upperBoundX = xMax; lowerBoundY = yMin; upperBoundY = yMax; xyToRowColumn(0.0, 0.0, zeroRow, zeroColumn); if ( (0 <= zeroColumn) && (zeroColumn < GRID_SIZE ) ) for (row = 0; row < GRID_SIZE ; row++) grid[row][zeroColumn] = '|'; if ( (0 <= zeroRow) && (zeroRow < GRID_SIZE ) ) for (column = 0; column < GRID_SIZE ; column++) grid[zeroRow][column] = '-'; if ( (0 <= zeroColumn) && (zeroColumn < GRID_SIZE ) && (0 <= zeroRow) && (zeroRow < GRID_SIZE ) ) grid[zeroRow][zeroColumn] = '+'; return; } // Member function markGrid: Determines the row and column associated // with the parameterized x/y coordinates, and then marks the grid // slot with that row and that column with the parameterized symbol. void ImageGrid::markGrid(double x, double y, char symbol) { int row, column; xyToRowColumn(x, y, row, column); if ( (0 <= column) && (column < GRID_SIZE) && (0 <= row) && (row < GRID_SIZE) ) grid[row][column] = symbol; } // Member function drawLine: Uses the parameterized slope and y-intercept to // mark the grid points comprising the corresponding line. If the slope // is steep, the iteration is row-by-row, otherwise, it's column-by-column. void ImageGrid::drawLine(double slope, double intercept, char symbol) { int row, column, index; double x, y; if ( (slope <= 1.0) && (slope >= -1.0) ) for (index = 0; index < 2*GRID_SIZE; index++) { x = lowerBoundX + index * (upperBoundX - lowerBoundX) / (2*GRID_SIZE - 1); y = slope * x + intercept; xyToRowColumn(x, y, row, column); if ( (0 <= column) && (column < GRID_SIZE) && (0 <= row) && (row < GRID_SIZE) ) grid[row][column] = symbol; } else for (index = 0; index < 2*GRID_SIZE; index++) { y = lowerBoundY + index * (upperBoundY - lowerBoundY) / (2*GRID_SIZE - 1); x = (y - intercept) / slope; xyToRowColumn(x, y, row, column); if ( (0 <= column) && (column < GRID_SIZE) && (0 <= row) && (row < GRID_SIZE) ) grid[row][column] = symbol; } } // Output Operator: Overloaded output // operator that outputs the grid to // the parameterized output file. ostream& operator << (ostream &outputFile, const ImageGrid &image) { int row, column; for (row = 0; row < GRID_SIZE; row++) { for (column = 0; column < GRID_SIZE; column++) outputFile << image.grid[row][column]; outputFile << endl; } return outputFile; } #define IMAGE_GRID_H #endif ///////////////////////////////////////////////////////////////////////////// // LinearRegression.cpp // // This driver program generates a grid of characters that graphs a set of // // 2D points (from a user-specified input file) and the least-squares line // // that most closely fits that set of points. // ///////////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <string> #include "Statistics.h" #include "ImageGrid.h“ using namespace std; void void void void retrievePairs(double* &x, double* &y, int &size); countPairs(string fileName, int &size); outputResults(const double x[], const double y[], int n, double m, double b); setXYBoundaries(const double x[], const double y[], int n, double &lowX, double &highX, double &lowY, double &highY); // The main function coordinates the retrieval of the data set // of ordered pairs, the least-square-fit, and the final output. void main() { double* xValue, yValue; int listSize; double lineSlope, intercept; retrievePairs(xValue, yValue, listSize); linearRegression(xValue, yValue, listSize, lineSlope, intercept); outputResults(xValue, yValue, listSize, lineSlope, intercept); return; } // The retrievePairs function fills the pair of parallel arrays // with ordered pairs of data from a user-specified file. void retrievePairs(double* &x, double* &y, int &size) { string fileName; ifstream inputFile; int index; cout << "Specify the name of the file containing the ordered pairs: "; cin >> fileName; countPairs(fileName, size); x = new double[size]; y = new double[size]; inputFile.open(fileName.c_str()); for (index = 0; index < size; index++) { inputFile >> x[index]; inputFile >> y[index]; } inputFile.close(); return; } // The countPairs function determines the number // of ordered pairs of values that exist in the // input file with the parameterized name. void countPairs(string fileName, int &size) { ifstream inputFile; double newX, newY; } inputFile.open(fileName.c_str()); size = 0; inputFile >> newX; while (!inputFile.eof()) { // The outputResults function sets up and completes inputFile >> newY; // an image grid by marking it with then points in size++; // the parameterized pair of parallel arrays, and inputFile >> newX; // by drawing the least-squares line-fit. } void outputResults(const double x[], const double y[], inputFile.close(); int n, double m, double b) return; { double lowX, highX, lowY, highY; ImageGrid image; int index; setXYBoundaries(x, y, n, lowX, highX, lowY, highY); image.initializeGrid(lowX, highX, lowY, highY); image.drawLine(m, b, '*'); for (index = 0; index < n; index++) image.markGrid(x[index], y[index], 'O'); cout << "The resulting linear regression: " << endl; cout << image << endl; } // The setXYBoundaries function finds lower and upper bounds for // the parameterized lists of x-values and y-values, adjusting // these boundaries so the gap between them is identical. void setXYBoundaries(const double x[], const double y[], int n, double &lowX, double &highX, double &lowY, double &highY) { lowX = minimum(x, n); highX = maximum(x, n); lowY = minimum(y, n); highY = maximum(y, n); if ( highX - lowX > highY - lowY ) { highY = (highY + lowY) / 2 + (highX - lowX) / 2; lowY = (highY + lowY) / 2 - (highX - lowX) / 2; } else { highX = (highX + lowX) / 2 + (highY - lowY) / 2; lowX = (highX + lowX) / 2 - (highY - lowY) / 2; } return; } 35.9 27.7 22.8 17.4 12.1 10.8 9.2 4.3 0.2 -1.5 -7.0 -12.6 -19.8 24.1 15.6 19.2 10.6 10.2 7.5 5.7 9.0 1.7 4.4 -10.1 -7.9 -15.3 (x0, f(x0)) x0 - 1 x0 - 2 x0 - 3 x0 x0 + 3 x0 + 2 x0 + 1 lowerX lowerX + 2 lowerX lowerX++2 12 lowerX + 32 upperX /////////////////////////////////////////////////////////////// // NumericalCalculus.cpp // // This program asks the user to select from five functions, // // and then provides an approximation of the derivative of // // that function at a user-specified x-value, as well as an // // approximation of the definite integral of that function // // between two user-specified x-values. // /////////////////////////////////////////////////////////////// #include <iostream> #include <cmath> #include <string> using namespace std; int queryUserForFunction(); string functionName(int id); double evaluate(int id, double x); void queryUserForDifferentiation(int id); void queryUserForDefiniteIntegral(int id); // The main function formats the output and coordinates the // user queries for the function, the x-value at which the // derivative will be estimated, and the x-values between // which the definite integral will be estimated. void main() { int functionID = queryUserForFunction(); cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(6); queryUserForDifferentiation(functionID); queryUserForDefiniteIntegral(functionID); return; } // The queryUserForFunction function provides the user with // a set of functions from which to make a selection. int queryUserForFunction() { int id; cout << "NUMERICAL CALCULUS APPROXIMATOR" << endl; cout << "-------------------------------" << endl; cout << "Available Functions:" << endl; for (id = 1; id <= 5; id++) cout << " " << id << ": " << functionName(id) << endl; cout << endl << "Specify which function you wish to test: "; cin >> id; while ( (id < 0) || (id > 5) ) { cout << "You must enter a number between 1 and 5: "; cin >> id; } return id; } // The functionName function returns a string corresponding to the user-selected function. string functionName(int id) { string name; switch (id) { case 1: { name = "3 * x^2 + 5 * x - 8"; break; } case 2: { name = "sin(x^2 + 4)"; break; } case 3: { name = "e^(-2 * x + 7)"; break; } case 4: { name = "5 * x^3 * cos(x / (x^2 + 1))"; break; } case 5: { name = "(4 * x^7 - 3 * x ^ 3 + 9) / (sin^2(4 * x) + 2 * x^2 + 10)"; break; } default: { name = ""; break; } } return name; } // The evaluate function returns the value that would be obtained // by applying the identified function at the parameterized x-value. double evaluate(int id, double x) { double y; switch (id) { case 1: { y = 3 * x * x + 5 * x - 8; break; } case 2: { y = sin(x * x + 4); break; } case 3: { y = exp(-2 * x + 7); break; } case 4: { y = 5 * pow(x, 3) * cos(x / (x * x + 1)); break; } case 5: { y = (4 * pow(x, 7) - 3 * pow(x, 3) + 9) / (pow(sin(4 * x), 2) + 2 * x * x + 10); break; } default: { y = 0.0; break; } } return y; } // The queryUserForDifferentiation function asks the user to specify an x-value at // which it will apply the central difference formula repeatedly until it produces an // approximation of the derivative of the identified function at the specified x-value. void queryUserForDifferentiation(int id) { const int ITERATION_LIMIT = 25; const double EPSILON = 0.0000001; double xValue; double preY, postY; double delta = 1.0; int iteration = 0; double oldDeriv, newDeriv; bool converged = false; cout << endl << endl << "Derivative Estimation:" << endl; cout << "Specify the x-value at which the derivative is to be estimated: "; cin >> xValue; preY = evaluate(id, xValue - delta); postY = evaluate(id, xValue + delta); newDeriv = (postY - preY) / (2 * delta); while ( (!converged) && (iteration < ITERATION_LIMIT) ) { iteration++; oldDeriv = newDeriv; delta /= 2.0; preY = evaluate(id, xValue - delta); postY = evaluate(id, xValue + delta); newDeriv = (postY - preY) / (2 * delta); converged = (fabs(newDeriv - oldDeriv) < EPSILON); } if (converged) { cout << endl << "For function f(x) = " << functionName(id) << endl << "at x = " << xValue << ", the function value is " << "f(" << xValue << ") = " << evaluate(id, xValue) << endl << "and the derivative is f'(" << xValue << ") = " << newDeriv << "." << endl; } else cout << endl << "NO DERIVATIVE CONVERGENCE AFTER " << ITERATION_LIMIT << " ATTEMPTS." << endl; return; } // The queryUserForDefiniteIntegral function asks the user to specify two // x-values to serve as upper and lower bounds for the application of the // trapezoidal formula for approximating a definite integral. This formula is // then applied repeatedly until it produces a convergent approximation of the // definite integral of the identified function between the specified x-values. void queryUserForDefiniteIntegral(int id) { const int ITERATION_LIMIT = 25; const double EPSILON = 0.0000001; double lowerX, upperX; double preSum, postSum; double delta; int iteration = 0; bool converged = false; int i; double lowTrapezoidX, highTrapezoidX, lowTrapezoidY, highTrapezoidY; cout << endl << endl << "Definite Integral Estimation:" << endl; cout << "Specify the lower x-value for the definite integral being estimated: "; cin >> lowerX; cout << "Specify the upper x-value for the definite integral being estimated: "; cin >> upperX; while (lowerX >= upperX) { cout << "The upper x-value must be greater than the lower x-value. Try again: "; cin >> upperX; } delta = upperX - lowerX; postSum = (evaluate(id, lowerX) + evaluate(id, upperX)) * delta / 2; while ( (!converged) && (iteration < ITERATION_LIMIT) ) { iteration++; preSum = postSum; delta /= 2.0; postSum = 0.0; for (i = 0; i < int(pow(2.0, iteration)); i++) { lowTrapezoidX = lowerX + i * delta; lowTrapezoidY = evaluate(id, lowTrapezoidX); highTrapezoidX = lowTrapezoidX + delta; highTrapezoidY = evaluate(id, highTrapezoidX); postSum += (lowTrapezoidY + highTrapezoidY) * delta / 2; } converged = (fabs(postSum - preSum) < EPSILON); } if (converged) { cout << endl << "For function f(x) = " << functionName(id) << endl << "between x = " << lowerX << " and x = " << upperX << endl << "the definite integral is " << postSum << "." << endl << endl << endl; } else cout << endl << "NO DEFINITE INTEGRAL CONVERGENCE AFTER " << ITERATION_LIMIT << " ATTEMPTS." << endl << endl << endl; return; }