+ All Categories
Home > Documents > CHAPTER 8 Multidimensional Arrays

CHAPTER 8 Multidimensional Arrays

Date post: 24-Feb-2016
Category:
Upload: baakir
View: 79 times
Download: 0 times
Share this document with a friend
Description:
CHAPTER 8 Multidimensional Arrays. Arrays of Arrays Matrix Operations. CHAPTER 8 – Multidimensional Arrays. 116. ARRAYS OF ARRAYS. //////////////////////////////////////////////////// // OneWeekGrid.h // - PowerPoint PPT Presentation
Popular Tags:
59
CHAPTER 8 Multidimensional Arrays Arrays of Arrays Matrix Operations CHAPTER 8 – Multidimensional Arrays 1
Transcript
Page 1: CHAPTER 8 Multidimensional Arrays

CHAPTER 8Multidimensional Arrays

•Arrays of Arrays•Matrix Operations

CHAPTER 8 – Multidimensional Arrays 1

Page 2: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 2

ARRAYS OF ARRAYS

////////////////////////////////////////////////////// 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 <iostream>#include <iomanip>#include <fstream>#include <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];};

Note that the itemCount data

member has been defined as a 7-row, 24-column array of

integers.

When a grid of values is needed in a program, the notion of a linear, one-dimensional array can be extended into additional dimensions by essentially making an array of arrays.

Page 3: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 3

// 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];

Note that the itemCount data member is loaded with values in

each constructor by using a nested for-loop, with the inner

loop traversing the columns and the outer loop traversing the

rows.

Page 4: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 4

// 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;}

Another nested for-loop to traverse the entire

two-dimensional array.

Page 5: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 5

// 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

In this nested for-loop, the inner loop lines up the values in each

row so they form output columns, while the outer loop ensures that each row starts with a day-of-the-week label

and ends with a linefeed.

Page 6: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 6

//////////////////////////////////////////////////////// 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 <iostream>#include <fstream>#include <string>#include "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();

The driver program starts by loading the

two-dimensional array with

contents of a user-defined

input file, using its own loadGrid

function.

Page 7: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 7

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;}

The driver program finishes by outputting the two-

dimensional array via the overloaded output operator in the OneWeekGrid class.

The loadGrid function uses the addItem member

function of the OneWeekGrid class in order to update each value in the two-dimensional array that

comprises the data member of that class.

Page 8: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 8

Tuesday 2100Thursday 1116Saturday 0159Friday 1339Sunday 1602Thursday 0156Sunday 0446Sunday 1816Saturday 0829Monday 1414Wednesday 0414Monday 0310Wednesday 2001Friday 1201Monday 1008Saturday 1830Wednesday 1911Tuesday 1921Monday 2055Monday 2354Wednesday 1640Monday 2359Monday 0603Thursday 0801Friday 1557

Saturday 1336Friday 0718Friday 0803Tuesday 0111Monday 1138Sunday 0118Sunday 1317Friday 1916Saturday 1032Saturday 0632Sunday 1458Monday 1957Tuesday 2131Monday 0237Saturday 1308Saturday 1536Tuesday 1516Sunday 1715Wednesday 0150Monday 0823Sunday 1717Thursday 0549Monday 0340Thursday 0759Tuesday 1532

Saturday 1021Sunday 1039Wednesday 0705Tuesday 1016Thursday 0806Wednesday 0823Sunday 1427Thursday 2256Sunday 1734Tuesday 1316Thursday 0645Thursday 0737Thursday 0321Saturday 0503Sunday 1118Tuesday 1300Thursday 2010Sunday 2301Tuesday 0431Thursday 0210Saturday 1928Friday 0628Thursday 1606Saturday 1711Tuesday 2119

Monday 1342Thursday 0601Sunday 1053Tuesday 0945Saturday 0305Wednesday 0704Sunday 1110Saturday 0541Monday 0520Wednesday 0636Sunday 1406Tuesday 1612Wednesday 0700Friday 1501Saturday 0633Monday 0330Wednesday 0943Wednesday 1129Sunday 0436Tuesday 1731Saturday 1500Friday 1325Friday 1631Friday 1311Thursday 1850

Saturday 0116Monday 1331Tuesday 1125Thursday 0010Monday 0439Friday 2128Monday 1342Saturday 2109Saturday 2144Saturday 1709Wednesday 0741Saturday 0157Sunday 1744Friday 1025Saturday 0212Saturday 1719Tuesday 2303Sunday 1708Saturday 2047Tuesday 1326Thursday 1839Thursday 2056Wednesday 1443Thursday 0907Tuesday 0634

Friday 1905Friday 0404Thursday 2038Wednesday 0419Tuesday 1325Monday 0537Tuesday 1708Monday 1503Monday 2200Wednesday 2126Tuesday 2221Thursday 2048Monday 1910Wednesday 0032Monday 0823Thursday 2305Sunday 2216Saturday 2029Friday 0800Monday 0841Tuesday 0834Monday 0407Monday 0439Tuesday 0737Wednesday 1902

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- SUNDAY: 112 139 121 127 126 105 104 119 116 124 113 132 119 118 116 105 117 124 117 108 140 112 113 113 MONDAY: 123 118 131 131 105 102 129 109 134 116 124 116 116 111 118 124 127 133 111 126 128 123 105 110 TUESDAY: 111 132 134 113 128 108 141 119 108 122 115 106 126 118 127 117 117 125 90 103 130 108 97 102 WEDNESDAY: 138 134 117 121 91 123 118 125 104 142 130 130 101 137 120 120 128 121 124 125 117 111 114 136 THURSDAY: 118 126 127 111 124 111 121 116 135 134 110 90 113 120 143 100 127 109 126 108 118 126 107 132 FRIDAY: 129 138 117 127 116 105 114 126 126 145 110 110 120 117 125 127 133 121 118 130 105 113 108 127 SATURDAY: 106 128 116 113 114 119 120 110 111 138 138 105 122 130 101 126 108 133 111 133 133 93 92 107

Page 9: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 9

MATRIX OPERATIONS// 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 DEFINITIONclass 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];};

Two-dimensional arrays may be used to represent matrices, making it possible to implement linear algebra problems.

Page 10: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 10

// 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;}

Page 11: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 11

// 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; } }

Page 12: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 12

// 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;}

When converting a matrix into reduced row echelon form, if the same operations are simultaneously applied to an identity matrix, the identity matrix is transformed into the inverse of the original matrix.

Page 13: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 13

// 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;}

Page 14: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 14

// 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;}

Page 15: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 15

// 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

Page 16: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 16

// 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;}

Page 17: CHAPTER 8 Multidimensional Arrays

CHAPTER 8 – Multidimensional Arrays 17

MATRIX A: 3.500 2.400 1.000 -4.600 -1.700 0.000 4.700 2.100 6.600 4.800 -5.000 1.600 2.100 -8.500 3.500 -7.400

MATRIX B: -6.400 1.200 6.100 -4.700 0.100 7.400 -0.500 5.300 4.200 0.000 8.400 -8.500 5.300 -7.100 6.600 1.200

DIAGONAL OF B: -6.400 7.400 8.400 1.200

SUM (A+B): -2.900 3.600 7.100 -9.300 -1.600 7.400 4.200 7.400 10.800 4.800 3.400 -6.900 7.400 -15.600 10.100 -6.200

DIFFERENCE (A-B): 9.900 1.200 -5.100 0.100 -1.800 -7.400 5.200 -3.200 2.400 4.800 -13.400 10.100 -3.200 -1.400 -3.100 -8.600

MATRIX PRODUCT (A*B): -42.340 54.620 -1.810 -17.750 41.750 -16.950 42.970 -29.440 -54.280 32.080 6.420 38.840 -38.810 -7.840 -2.380 -93.550

SCALAR PRODUCT (5*B): -32.000 6.000 30.500 -23.500 0.500 37.000 -2.500 26.500 21.000 0.000 42.000 -42.500 26.500 -35.500 33.000 6.000

INVERSE OF A: -0.027 0.120 0.169 0.088 0.147 -0.004 -0.046 -0.102 0.057 0.197 0.013 0.023 -0.149 0.132 0.107 0.018

PRODUCT OF A AND ITS INVERSE: 1.000 0.000 0.000 0.000 0.000 1.000 -0.000 -0.000 -0.000 0.000 1.000 -0.000 0.000 -0.000 -0.000 1.000

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

MatrixData1.txt

MatrixData2.txt

MatrixResults.txt

Page 18: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 18

CHAPTER 9Input and Output Streams

•Escape Sequences•Formatting Output

Page 19: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 19

ESCAPE SEQUENCES

#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);}

Because of the syntax rules of C++, some characters require special escape sequences to accomplish output.

Page 20: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 20

void printHeader(){ cout << " ESCAPE SEQUENCE TESTER" << endl; cout << " ----------------------" << endl; cout << "This application tests each of the C++ escape" << endl; cout << "sequences by verifying that you are ready for" << endl; cout << "the next one, and then using it in output six" << endl; cout << "times, with every time preceded by an ordinal" << endl; 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;}

Page 21: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 21

Page 22: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 22

FORMATTING OUTPUT#include <iostream>

#include <iomanip>#include <fstream>#include <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;}

With the inclusion of the iomanip library, additional output formatting options are made available.

Page 23: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 23

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 loadArray(double list[], int listSize){ int index; ifstream inputFile; inputFile.open(INPUT_FILE_NAME.c_str()); for (index = 0; index < listSize; index++) inputFile >> list[index]; inputFile.close(); return;}

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 rightFormatOutput(double list[], int listSize){ ofstream outputFile; outputFile.open(RIGHT_OUTPUT_FILE_NAME.c_str()); outputFile.setf(ios::right); outputFile.setf(ios::fixed); outputFile.setf(ios::showpoint); outputFile.precision(2); outputArray(outputFile, list, listSize); outputFile.close(); return;}

Page 24: CHAPTER 8 Multidimensional Arrays

CHAPTER 9 – Input and Output Streams 24

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.1415998.62.718280.57721566491.618033988749896.02214199-2.0023193-3.82608545-273.15

LeftOutput.txt

RightOutput.txt

Source.txtCOLUMN 1 COLUMN 2 COLUMN 3 3.1416 98.6000 2.7183 0.5772 1.6180 6.0221 -2.0023 -3.8261 -273.1500

COLUMN 1 COLUMN 2 COLUMN 3 3.14 98.60 2.72 0.58 1.62 6.02 -2.00 -3.83 -273.15

Page 25: CHAPTER 8 Multidimensional Arrays

CHAPTER 10- Introduction to Numerical Methods 25

CHAPTER 10Introduction to Numerical Methods•Roots of Functions•Statistics•Numerical Differentiation•Numerical Integration

Page 26: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 26

ROOTS OF FUNCTIONSOne common numerical method using derivatives is Newton’s Method, which attempts to locate an approximation to a root of a function.

x0

(First Guess)

(x0, f(x0)

x1 = x0 – f(x0)/f(x0)x2 = x1 – f(x1)/f(x1)(x1, f(x1)

Page 27: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 27

NEWTON’S METHOD////////////////////////////////////////////////////////////////////////// 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;};

Page 28: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 28

// 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]; }}

Page 29: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 29

// 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;}

Page 30: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 30

// 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;}

Page 31: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 31

// 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];

Page 32: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 32

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

Page 33: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 33

/////////////////////////////////////////////////////////////////////// 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);}

Page 34: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 34

// 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;}

Page 35: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 35

// 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;

Page 36: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 36

// 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 the iterative process terminates due to // convergence, then the approximate root is output. // Otherwise, the failure of the method is reported. if (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;}

Page 37: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 37

Page 38: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 38

STATISTICSOne common statistical approach, the least-squares method, uses linear regression to determine the closest line that fits a set of points.

Page 39: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 39

LINEAR REGRESSION////////////////////////////////////////////////////// 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;}

Page 40: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 40

// 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 );}

Page 41: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 41

// 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

Page 42: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 42

//////////////////////////////////////////////////////////////////////////////////// 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;};

Page 43: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 43

// 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;}

Page 44: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 44

// 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;}

Page 45: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 45

// 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; }}

Page 46: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 46

// 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 retrievePairs(double* &x, double* &y, int &size);void countPairs(string fileName, int &size);void outputResults(const double x[], const double y[], int n, double m, double b);void setXYBoundaries(const double x[], const double y[], int n, double &lowX, double &highX, double &lowY, double &highY);

Page 47: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 47

// 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;}

Page 48: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 48

// 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()) { inputFile >> newY; size++; inputFile >> newX; } inputFile.close(); return;}

// The outputResults function sets up and completes// an image grid by marking it with then points in// the parameterized pair of parallel arrays, and// by drawing the least-squares line-fit.void outputResults(const double x[], const double y[], int n, double m, double b){ 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;}

Page 49: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 49

// 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;}

Page 50: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 50

35.9 24.1 27.7 15.6 22.8 19.2 17.4 10.6 12.1 10.2 10.8 7.5 9.2 5.7 4.3 9.0 0.2 1.7 -1.5 4.4 -7.0 -10.1-12.6 -7.9-19.8 -15.3

points.txt

Page 51: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 51

NUMERICAL CALCULUS

x0x0 - 1 x0 + 1

(x0, f(x0))

x0 - 2 x0 + 2 x0 - 3 x0 + 3

When the closed form of a derivative is difficult to formulate, differentiation at a particular x-value may be approximated via the central difference formula.

Page 52: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 52

When the closed form of an integral is difficult to formulate, a definite integral between two x-values may be approximated via the trapezoid method.

lowerX + 1lowerX upperXlowerX + 2 lowerX + 32lowerX + 22

Page 53: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 53

///////////////////////////////////////////////////////////////// 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;}

Page 54: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 54

// 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;}

Page 55: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 55

// 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;

Page 56: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 56

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;}

Page 57: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 57

// 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;

Page 58: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 58

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;}

Page 59: CHAPTER 8 Multidimensional Arrays

CHAPTER 10 – Introduction to Numerical Methods 59


Recommended