Chapter 8

advertisement
////////////////////////////////////////////////////
// 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 + 32
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;
}
Download