package ps1; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** RatPoly represents an immutable single-variate polynomial expression. RatPolys have RatNum coefficients and integer exponents.
Examples of RatPolys include "0", "x-10", and "x^3-2*x^2+5/3*x+3",
and "NaN".
*/
public class RatPoly {
/** holds all the RatTerms in this RatPoly */
private List
There is no whitespace in the returned string.
If the polynomial is itself zero, the returned string will
just be "0".
If this.isNaN(), then the returned string will be just "NaN"
The string for a non-zero, non-NaN poly is in the form
"(-)T(+|-)T(+|-)...",where for each
term, T takes the form "C*x^E" or "C*x", UNLESS:
(1) the exponent E is zero, in which case T takes the form "C", or
(2) the coefficient C is one, in which case T takes the form
"x^E" or "x"
Note that this format allows only the first term to be output
as a negative expression.
Valid example outputs include "x^17-3/2*x^2+1", "-x+1", "-1/2",
and "0".
*/
public String unparse() {
//TODO: Fill in this method, then remove the RuntimeException
throw new RuntimeException("RatPoly->unparse() unimplemented!");
}
/** Scales coefficients within 'list' by 'scalar' (helper procedure).
@requires list, scalar != null
@modifies list
@effects Forall i s.t. 0 <= i < list.size(),
if (C . E) = list.get(i)
then list_post.get(i) = (C*scalar . E)
@see ps1.RatTerm regarding (C . E) notation
*/
private static void scaleCoeff(List
Division of polynomials is defined as follows:
Given two polynomials u and v, with v != "0", we can divide u by
v to obtain a quotient polynomial q and a remainder polynomial
r satisfying the condition u = "q * v + r", where
the degree of r is strictly less than the degree of v,
the degree of q is no greater than the degree of u, and
r and q have no negative exponents.
For the purposes of this class, the operation "u / v" returns
q as defined above.
Thus, "x^3-2*x+3" / "3*x^2" = "1/3*x" (with the corresponding
r = "-2*x+3"), and "x^2+2*x+15 / 2*x^3" = "0" (with the
corresponding r = "x^2+2*x+15").
Note that this truncating behavior is similar to the behavior
of integer division on computers.
*/
public RatPoly div(RatPoly p) {
checkRep();
// Check for NaN
if (p.isNaN() || isNaN()) {
//TODO: Return a NaN RatPoly, then remove the RuntimeException
throw new RuntimeException("RatPoly->div(): NaN RatPoly not defined!");
}
// Check for zero RatPoly in this and in p
//TODO: Return a Zero RatPoly if this is a Zero RatPoly, then
// remove the RuntimeException
if (p.isZero() || isZero()) {
throw new RuntimeException("RatPoly->div(): Zero RatPoly not checked!");
}
// The rest of the method has been provided to you by the staff:
// Start with a new polynomial
List The derivative of a polynomial is the sum of the
derivative of each term.
Given a term, a*x^b, the derivative of the term is:
(a*b)*x^(b-1) for b > 0 and 0 for b == 0
*/
public RatPoly differentiate() {
//TODO: Fill in this method, then remove the RuntimeException
throw new RuntimeException("RatPoly->differentiate() unimplemented!");
}
/** Returns the antiderivative of this RatPoly.
@requires integrationConstant != null
@return a new RatPoly that, q, such that dq/dx = this
and the constant of integration is "integrationConstant"
In other words, q is the antiderivative of this.
If this.isNaN() or integrationConstant.isNaN(),
then return some q such that q.isNaN()
The antiderivative of a polynomial is the sum of the
antiderivative of each term plus some constant.
Given a term, a*x^b, (where b >= 0)
the antiderivative of the term is: a/(b+1)*x^(b+1)
*/
public RatPoly antiDifferentiate(RatNum integrationConstant) {
//TODO: Fill in this method, then remove the RuntimeException
throw new RuntimeException("RatPoly->antiDifferentiate() unimplemented!");
}
/** Returns the integral of this RatPoly, integrated from
lowerBound to upperBound.
@return a double that is the definite integral of this with
bounds of integration between lowerBound and upperBound.
The Fundamental Theorem of Calculus states that the definite integral
of f(x) with bounds a to b is F(b) - F(a) where dF/dx = f(x)
NOTE: Remember that the lowerBound can be higher than the upperBound
*/
public double integrate(double lowerBound, double upperBound) {
//TODO: Fill in this method, then remove the RuntimeException
throw new RuntimeException("RatPoly->integrate() unimplemented!");
}
/** Returns the value of this RatPoly, evaluated at d.
@return the value of this polynomial when evaluated at 'd'.
For example, "x+2" evaluated at 3 is 5, and "x^2-x"
evaluated at 3 is 6.
if (this.isNaN() == true), return Double.NaN
*/
public double eval(double d) {
//TODO: Fill in this method, then remove the RuntimeException
throw new RuntimeException("RatPoly->eval() unimplemented!");
}
/** Builds a new RatPoly, given a descriptive String.
@requires 'polyStr' is an instance of a string with no spaces
that expresses a poly in the form defined in the
unparse() method.
Valid inputs include "0", "x-10", and "x^3-2*x^2+5/3*x+3",
and "NaN".
@return a RatPoly p such that p.unparse() = polyStr
*/
public static RatPoly parse(String polyStr) {
RatPoly result = new RatPoly();
// First we decompose the polyStr into its component terms;
// third arg orders "+" and "-" to be returned as tokens.
StringTokenizer termStrings =
new StringTokenizer(polyStr, "+-", true);
boolean nextTermIsNegative = false;
while (termStrings.hasMoreTokens()) {
String termToken = termStrings.nextToken();
if (termToken.equals("-")) {
nextTermIsNegative = true;
} else if (termToken.equals("+")) {
nextTermIsNegative = false;
} else {
// Not "+" or "-"; must be a term
// Term is: "R" or "R*x" or "R*x^N" or "x^N" or "x",
// where R is a rational num and N is a natural num.
// Decompose the term into its component parts.
// third arg orders '*' and '^' to act purely as delimiters.
StringTokenizer numberStrings =
new StringTokenizer(termToken, "*^", false);
RatNum coeff;
int expt;
String c1 = numberStrings.nextToken();
if (c1.equals("x")) {
// ==> "x" or "x^N"
coeff = new RatNum(1);
if (numberStrings.hasMoreTokens()) {
// ==> "x^N"
String N = numberStrings.nextToken();
expt = Integer.parseInt(N);
} else {
// ==> "x"
expt = 1;
}
} else {
// ==> "R" or "R*x" or "R*x^N"
String R = c1;
coeff = RatNum.parse(R);
if (numberStrings.hasMoreTokens()) {
// ==> "R*x" or "R*x^N"
String x = numberStrings.nextToken();
if (numberStrings.hasMoreTokens()) {
// ==> "R*x^N"
String N = numberStrings.nextToken();
expt = Integer.parseInt(N);
} else {
// ==> "R*x"
expt = 1;
}
} else {
// ==> "R"
expt = 0;
}
}
// at this point, coeff and expt are initialized.
// Need to fix coeff if it was preceeded by a '-'
if (nextTermIsNegative) {
coeff = coeff.negate();
}
// accumulate terms of polynomial in 'result'
if (!coeff.equals(new RatNum(0))) {
RatPoly termPoly = new RatPoly();
termPoly.terms.add(new RatTerm(coeff, expt));
result = result.add(termPoly);
}
}
}
result.checkRep();
return result;
}
/** Checks to see if the representation invariant is being violated and if so, throws RuntimeException
@throws RuntimeException if representation invariant is violated
*/
private void checkRep() throws RuntimeException {
if (terms == null) {
assert(false) : "CheckRep assert";
throw new RuntimeException("terms == null!");
}
for (int i=0; i < terms.size(); i++) {
if ((terms.get(i).coeff.compareTo(new RatNum(0)))==0) {
throw new RuntimeException("zero coefficient!");
}
if (terms.get(i).expt < 0) {
throw new RuntimeException("negative exponent!");
}
if (i < terms.size() - 1) {
if (terms.get(i+1).expt >= terms.get(i).expt) {
throw new RuntimeException("terms out of order!");
}
}
}
}
}