Referring to an array in a subclass - java

So im writing a program to add and subtract Polynomials. The Polynomial is comes in as a String (example: 4x^7-2x^5+3x^2+78) and its split up into Terms (example 4x^7) and then the coefficient value is assigned to PolynomialArray[exponent].
This is part one of my assignment so I have an Interface that was given to me below:
public interface PolynomialInterface {
PolynomialInterface add(PolynomialInterface other);
// Effect: Adds value to owner of addPolynomial method.
// Postcondition: Return value = this + value.
PolynomialInterface subtract(PolynomialInterface other);
// Effect: Subtracts value from owner of addPolynomial method.
// Postcondition: Return value = this - value.
void readPolynomial();
// Postcondition: polynomial read.
String toString();
// Postcondition: polynomial converted to string.
}
Heres my code so far:
import java.lang.*;
public class ArrayWithExponentAsIndexPolynomial implements PolynomialInterface {
Integer PolynomialArray[] = new Integer[1000];
CharSequence minus = "-";
CharSequence plusMinus = "+-";
boolean FirstElementPos = true;
public ArrayWithExponentAsIndexPolynomial(String input) {
if (input.charAt(0) == '-') {
input = input.substring(1);
FirstElementPos = false;
}
String inputPolynomial = input.replaceAll("-", "+-");
// input.replace(minus, plusMinus);
System.out.println(inputPolynomial);
String[] splitTerms = inputPolynomial.split("\\+");
// int PolynomialArray[] = new int[100];
for (int i = 0; i <= splitTerms.length - 1; i++) {
System.out.println(splitTerms[i]);
}
String tempTemp = splitTerms[1];
int coef;
int exponent;
String tempExp = null;
for (int i = 0; i < splitTerms.length; i++) {
String tempTerm = splitTerms[i];
System.out.println();
System.out.println("Term we are working with " + tempTerm);
boolean tempPos = true;
if (tempTerm.contains("-")) {
tempTerm = tempTerm.substring(1);
System.out.println("After removing negative from term: "
+ tempTerm);
tempPos = false;
}
int IndexOfexponent = tempTerm.indexOf('^');
if (IndexOfexponent == -1) {
exponent = 1;
// FirstElementPos = true;
} else {
tempExp = tempTerm.substring(IndexOfexponent + 1);
exponent = Integer.parseInt(tempExp);
}
System.out.println("The exp is " + exponent);
// String tempTerm = splitTerms[i];
System.out.println("The term rn is: " + tempTerm);
String tempTermNoCarrot = tempTerm.replaceAll("\\^" + tempExp, "");
String tempCoef = tempTermNoCarrot.replaceAll("x", "");
// String tempCoef = tempTermNoX.replaceAll(tempExp, "");
System.out.println("THe Coeff rn is: " + tempCoef);
coef = Integer.parseInt(tempCoef);
if (tempPos == false || FirstElementPos == false) {
coef = (coef * -1);
}
System.out.println("After everything, Coef is:" + coef
+ " and exp is: " + exponent);
PolynomialArray[exponent] = coef;
}
}
public PolynomialInterface add(PolynomialInterface other) {
String finalOutput=null;
//Integer top = this.PolynomialArray[i];
Integer Sum[] = new Integer[100];
for (int i = 99; i >= 1; i--){
Integer top = this.PolynomialArray[i];
Integer bottom = other.PolynomialArray[i];
Sum[i] = top + bottom;
}
String tempOutput = null;
for (int i = 99; i >= 1; i--) {
if (Sum[i] != null && Sum[i] != 0) {
tempOutput += "+";
int outputCoef = Sum[i];
tempOutput += outputCoef;
tempOutput += "x^";
tempOutput += i;
}
}
String RemoveNull = tempOutput;
tempOutput = RemoveNull.replaceAll("null", "");
if (tempOutput.charAt(0) == '+') {
tempOutput = tempOutput.substring(1);
}
tempOutput = tempOutput.replaceAll("\\+-","-");
finalOutput = tempOutput;
return new ArrayWithExponentAsIndexPolynomial(finalOutput);
}
public PolynomialInterface subtract(PolynomialInterface other) {
return other;
}
public void readPolynomial() {
}
public String toString() {
String output = null;
for (int i = 99; i >= 1; i--) {
if (PolynomialArray[i] != null && PolynomialArray[i] != 0) {
output += "+";
int outputCoef = PolynomialArray[i];
output += outputCoef;
output += "x^";
output += i;
}
}
String outputTemp = output;
output = outputTemp.replaceAll("null", "");
if (output.charAt(0) == '+') {
output = output.substring(1);
}
output = output.replaceAll("\\+-","-");
return output;
}
}
My question is in the add mehthod, how do i refer to the PolynomialArray in the "other" object. When i do other.PolynomialArray[i] it says PolynomialArray cannot be resolved or is not a field sense in the Interface, there exists no such thing. Id there a way to refer to my intended target without changing the interface because in my future project I will need to use this
Sorry if I'm not being clear. This is my first time posting :)
*quick edit. I'm not done with my code so there are a few place holders here and there and some random print statements

Integer PolynomialArray[] = new Integer[1000];
This is something which your implementing Class ArrayWithExponentAsIndexPolynomial has added. It's not specified in your interface contract. You are trying to get the PolynomialArray[] from your interface reference. That won't work. You need to cast it like ((ArrayWithExponentAsIndexPolynomial)other).PolynomialArray[i];

Simply put, the PolynomialArray field is defined in your ArrayWithExponentAsIndexPolynomial class and unknown to the given PolynomialInterface inferface. In practice, only methods are defined in an interface, not fields (as Amit.rk3 mentioned, static final fields are allowed, though no solution to your problem). A way to access a field of an object indentified solely by an interface, is to define a getSomeField() method in the interface.
I'm not sure if your assignment allows you to add getPolynomialArray() to the given interface, but that would be the simplest solution.
Otherwise, though less elegant, you can cast the given object to your class and access the field directly.

Related

Class is not abstract and does not override abstract method error [duplicate]

This question already has answers here:
Class is not abstract and does not override abstract method
(2 answers)
Closed 3 years ago.
I've been working on a program that can find the root of a polynomial for school, and do various other polynomial related stuff like adding them together or finding the value of a polynomial with a given x. While the other two classes I made work fine (they find the root of a sin and cos function), my FuncPoly class seems to be conflicting with my evaluate method somehow, and doesn't want to inherit it. This is my exact error message:
.\FuncPoly.java:1: error: FuncPoly is not abstract and does not override abstract method evaluate(double) in Function
public class FuncPoly extends Function{
I've tried fiddling with the evaluate method a little bit and trying to add some overrides in, but it hasn't been helping me very much. I need help finding what is causing this error; maybe its related to my constructor?. Thanks for reading and your help! Code is below; there is a lot in there, but I don't think most of it is pertinent to the question.
public abstract double evaluate(double x); //Basically just a filler for SinFunc and CosFunc
public double findRoot(double a, double b, double epsilon){
double x = ( a + b ) / 2;
if (Math.abs( a - x) <= epsilon){
return x;
}else if (evaluate(x)*evaluate(a) >= 0){
return findRoot(x, b, epsilon);
}else{
return findRoot(a, x, epsilon);
}
}
public static void main(String[] args){
//Tests SinFunc and CosFunc
SinFunc q = new SinFunc();
CosFunc w = new CosFunc();
System.out.println("The root of sin(x) with the numbers entered with the given epsilon is: " + q.findRoot(3,4,.00000001));
System.out.println("The root of cos(x) with the numbers entered with the given epsilon is: " + w.findRoot(1,3,.00000001));
//Tests the FuncPoly stuff
int[] test1 = {1,0,-3};
int[] test2 = {1,-1,-2};
FuncPoly poly1 = new FuncPoly(test1);
FuncPoly poly2 = new FuncPoly(test2);
System.out.println("The root of x^2 + (-3) is" + poly1.findRoot(0,10,.00000001));
}
}
____________________________
public class FuncPoly extends Function{
public int coefficients[];
public FuncPoly(int[] coefficients){
//Constructor
this.coefficients = coefficients;
}
public int degree(){
//Finds the highest power by finding the location of the last number in the array.
return this.coefficients.length - 1;
}
public String toString(){
//Converts a polynomial to a string
StringBuilder poly = new StringBuilder();
for(int i = degree(); i >= 0; i--){
if (i == degree()){
poly.append(this.coefficients[i] + "x^" + degree());
}else{
if (this.coefficients[i] == 0){
System.out.println(i);
}else if (i == 0){
poly.append(" + " + this.coefficients[0]);
} else if ( i == 1){
poly.append(" + " + this.coefficients[1] + "x");
} else{
poly.append(" + " + this.coefficients[i] + "x^" + i);
}
}
}
return poly.toString();
}
public FuncPoly add(FuncPoly a){
//Adds the selected polynomial and the last called polynomial together and returns the array.
if (this.degree() > a.degree()){
int[] polyAdd = new int[this.degree() + 1];
for (int i = 0; i <= a.degree(); i++){
polyAdd[i] = a.coefficients[i] + this.coefficients[i];
}
for (int i = a.degree() + 1; i < this.degree() + 1; i++){
polyAdd[i] = this.coefficients[i];
}
FuncPoly polyResult = new FuncPoly(polyAdd);
return polyResult;
} else if (this.degree() < a.degree()){
int[] polyAdd = new int[a.degree() + 1];
for (int i = 0; i <= this.degree(); i++){
polyAdd[i] = a.coefficients[i] + this.coefficients[i];
}
for (int i = this.degree() + 1; i < degree() + 1; i++){
polyAdd[i] = a.coefficients[i];
}
FuncPoly polyResult = new FuncPoly(polyAdd);
return polyResult;
} else {
int[] polyAdd = new int[a.degree() + 1];
for (int i = 0; i < a.degree() + 1; i++){
polyAdd[i] = a.coefficients[i] + this.coefficients[i];
}
FuncPoly polyResult = new FuncPoly(polyAdd);
return polyResult;
}
}
public double value(double x){
//Finds the value of polynomial with a given x.
double sum = 0;
for(int i = 0; i < this.degree() + 1; i++){
sum += this.coefficients[i] * Math.pow(x,i);
}
return sum;
}
}
As far as I can tell, your value() method in FuncPoly needs to be renamed to evaluate() to successfully implement the abstract evaluate() method from the Function class.

Polynomial Add: Unable to run code

This program is on Eclipse. I have to declare variables "Integer" not "int". When I am compiling this code shows no error but there is a runtime error. Please fix this problem.
Runtime error:
Exception in thread "main" java.lang.NullPointerException
at Polynomial.add(Polynomial.java:17)
at PolynomialTest.main(PolynomialTest.java:7)
Polynomial.java
public class Polynomial{
Integer coef[];
Integer exp;
public Polynomial(Integer a, Integer b) {
coef = new Integer[b+1];
coef[b] = a;
exp = b;
}
// return c = a + b
public Polynomial add(Polynomial b) {
Polynomial a = this;
Polynomial c= new Polynomial(0, Math.max(a.exp, b.exp));
for (Integer i = 0; i <= a.exp; i++){
c.coef[i] = c.coef[i] + a.coef[i];
}
for (int i = 0; i <= b.exp; i++){
c.coef[i] += b.coef[i];
}
return c;
}
public String toString() {
if (exp == 0){
return "" + coef[0];
}else
if (exp == 1){
return coef[1] + "x + " + coef[0];
}
String s = coef[exp] + "x^" + exp;
for (int i = exp-1; i >= 0; i--) {
if (coef[i] == 0){
continue;
}
else if (coef[i] > 0){
s = s + " + " + ( coef[i]);
}
if (i == 1){
s = s + "x";
}
else
if (i > 1) {
s = s + "x^" + i;
}
}
return s;
}}
PolynomialTest.java
public class PolynomialTest {
// test client
public static void main(String[] args) {
Polynomial p1 = new Polynomial(4, 4);
Polynomial p2 = new Polynomial(7, 2);
Polynomial p3 = new Polynomial(3, 0);
Polynomial p = p1.add(p2).add(p3); // 4x^3 + 3x^2 + 1
Polynomial q1 = new Polynomial(2, 2);
Polynomial q2 = new Polynomial(5, 4);
Polynomial q = q1.add(q2);
System.out.println("p(x) = " + p);
System.out.println("q(x) = " + q);
System.out.println("p(x) + q(x) = " + p.add(q));
}
}
Since Integer is an Object, you will need to initialize each entry in your coef array with a new Integer object.
You could just do this in the Polynomial constructor:
public class Polynomial{
Integer coef[];
Integer exp;
public Polynomial(Integer a, Integer b) {
coef = new Integer[b+1];
for (int i = 0; i < coef.length; i++){
coef[i] = new Integer(0); //create a new Integer and initialize to zero
}
coef[b] = a;
exp = b;
}

How would I decompress a String recursively WITHOUT any for loops?

For my assignment, I have to be able to decompress a string recursively with no for loops. I'm having some trouble trying to limit myself from using for loops and I'd appreciate it if I could receive some assistance. Towards the end, I have a for loop and I was wondering if there was a way I could remove it with something else and still have my program do what I intend for it to do
public class StringRec {
public static void main(String[] args) {
System.out.println("What text do you want to decompress?");
String compressedText = IO.readString();
System.out.println(decompress(compressedText));
}
public static String decompress(String compressedText) {
if (compressedText.length()<=1){
return compressedText;
}
String first="";
String rest="";
char c = compressedText.charAt(0);
if (Character.isLetter(c) == true) {
first = compressedText.substring(0,1);
rest = compressedText.substring(1);
return first + decompress(rest);
} else {
first = compressedText.substring(1,2);
rest = compressedText.substring(2);
int x = compressedText.charAt(0)-'0';
char y = compressedText.charAt(1);
String tst = "";
for(int i = 0; i < x; i++) {
tst = tst+y;
}
return tst + decompress(rest);
}
}
}
Use a while loop to do the same thing.
int i = 0;
while(i < x) {
i++;
tst += y;
}
If you can't use loops altogether, then use recursion.
int i = 0;
public String recursiveAppend(String tst) {
if(i >= x) {
i = 0;
return tst;
}
else return recursiveAppend(tst + y);
}
If you're using > Java 1.5, then use String tst = new String(new char[x]).replace('\0', y);. (from here)
Recursion to the rescue, bonus point if it is tail recursive:
String tst = repeat(y, x, "");
...
private String repeat(y, x, b) {
if (x == 0) {
return b;
}
return repeat(y, x - 1, b + y) ;
}

How could I change my code to accept double values from the user?

import java.util.Scanner;
class MyCalculator {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Enter a expression : ");
while(input.hasNext()){
String exp = input.next();
System.out.println(""+exp+" = "+ Calculate(exp));
}
}
//define a method to decide the operators' priority
private static int priority(char input){
switch(input){
case'(' : return 3; //parenthesis have highest priority
case')' : return 3;
case'*' : return 2; //multiplication and division have lower priority than parenthesis
case'/' : return 2;
case'+' : return 1; //plus minus have lowest operator priority
case'-' : return 1;
default : return 0;//numbers have lowest priority
}
}
//now we define our big method Calculate
public static int Calculate(String exp){
//firstly we try to check if the exp is already a number or a simple expression
//or having high level operator
//the key recursive idea is to compute inner results if there is higher level operators
//until the result is return
char[] inputs = exp.toCharArray();//we process string to char arrays for easy control
//now we check the highest level operators and the count
int highestPriority =0;
int operatorCount =0;//this value is to keep track of how many operators remaining, mostly to deal with negative number cases
for(int i=0;i<inputs.length;i++)
{
if(priority(inputs[i])>highestPriority)
{
highestPriority = priority(inputs[i]);//update highest priority if necessary
}
if(priority(inputs[i])>0)
{
++operatorCount;
}
}
//after that we process in order
if(operatorCount==0)//no operator remaining
{
return Integer.parseInt(exp);//Immediately return the result
}
else if(highestPriority==1){//-+ remaining
//we firstly deal with the negative numbers
if(operatorCount==1 && inputs[0]=='-')//if only operator is the leading minus operator
{
return Integer.parseInt(exp);
}
//otherwise, we need to find the operatorand compute result
int opePosition = -1;//set as -1 as non set
boolean ifPlusSign = true;//this is to know if plus or minus sign
for(int i=0;i<inputs.length;i++)
{
//notice we may encounter the case of -1-1, thus the leading minus sign should be ignored
if(inputs[i]== '+' || (inputs[i]=='-' && i!=0))// we differenciate here because we need know if plus or minus sign
{
opePosition = i;
ifPlusSign = inputs[i] == '+'?true:false;
break;
}
}
//after we identify the opePosition, we need find start/end of left and right operand
int leftOperandStart = 0;
int rightOperandEnd = opePosition+1;
//we need to deal with negative value cases
if(inputs[rightOperandEnd]=='-')
{
rightOperandEnd++;
}
while(rightOperandEnd<inputs.length && priority(inputs[rightOperandEnd])<1)
{
rightOperandEnd++;
}
int leftOperand = Integer.parseInt(exp.substring(0, opePosition));
int rightOperand = Integer.parseInt(exp.substring(opePosition+1, rightOperandEnd));
int innerResult = 0;
if(ifPlusSign)
{
innerResult = leftOperand+rightOperand;
}
else
{
innerResult = leftOperand - rightOperand;
}
return Calculate(""+ innerResult+ exp.substring(rightOperandEnd));
}
else if(highestPriority==2)
{
// */ remaining
/*if(operatorCount==1 && inputs[0]=='-'){
return Integer.parseInt(exp);
}*/
int opePosition = -1;
boolean ifMultiplySign = true;//this is to know if plus or minus sign
for(int i=0;i<inputs.length;i++)
{
if(inputs[i]== '*' || (inputs[i]=='/' && i!=0))
{
opePosition = i;
ifMultiplySign = inputs[i] == '+'?true:false;
break;
}
}
int leftOperandStart = opePosition-1;
while(leftOperandStart>=0 && priority(inputs[leftOperandStart])<1)
{
leftOperandStart--;
}
int rightOperandEnd = opePosition+1;
if(inputs[rightOperandEnd]=='-')
{
rightOperandEnd++;
}
while( rightOperandEnd<inputs.length && priority(inputs[rightOperandEnd])<1)
{
rightOperandEnd++;
}
int leftOperand = Integer.parseInt(exp.substring(leftOperandStart+1, opePosition));
int rightOperand = Integer.parseInt(exp.substring(opePosition+1, rightOperandEnd));
int innerResult = 0;
if(ifMultiplySign)innerResult = leftOperand * rightOperand;
else innerResult = leftOperand / rightOperand;
return Calculate(exp.substring(0, leftOperandStart+1)+innerResult+exp.substring(rightOperandEnd));
}
else
{
int parOpen = -1;
int parEnd = -1;
int parOpenEndiff = 0;
for(int i=0;i<inputs.length;i++)
{
if(inputs[i]=='(')
{
parOpen=parOpen<0?i:parOpen;
parOpenEndiff++;
}
else if(inputs[i]==')')
{
parOpenEndiff--;
if(parOpenEndiff==0)
{
parEnd = i;
break;
}
}
}
int innerResult = Calculate(exp.substring(parOpen+1,parEnd));
return Calculate(exp.substring(0, parOpen)+innerResult+exp.substring(parEnd+1));
}
}
}
How could I change my code to accept double value from the user ? (actually this program works fine with int values ).please could you help me to customize the program for double values also .....
String exp = input.next(); --> double exp = input.nextDouble();
Or:
String exp = input.next();
double value = Double.parseDouble(exp);
Do double value = Double.parseDouble(exp); in switch default case.

what is wrong with this code when dealing with large values of "long"?

I wrote an utility class to encode numbers in a custom numeral system with base N. As any self-respecting Java programmer I then wrote a unit test to check that the code works as expected (for any number I could throw at it).
It turned out, that for small numbers, it worked. However, for sufficiently large numbers, the tests failed.
The code:
public class EncodeUtil {
private String symbols;
private boolean isCaseSensitive;
private boolean useDefaultSymbols;
private int[] symbolLookup = new int[255];
public EncodeUtil() {
this(true);
}
public EncodeUtil(boolean isCaseSensitive) {
this.useDefaultSymbols = true;
setCaseSensitive(isCaseSensitive);
}
public EncodeUtil(boolean isCaseSensitive, String symbols) {
this.useDefaultSymbols = false;
setCaseSensitive(isCaseSensitive);
setSymbols(symbols);
}
public void setSymbols(String symbols) {
this.symbols = symbols;
fillLookupArray();
}
public void setCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive;
if (useDefaultSymbols) {
setSymbols(makeAlphaNumericString(isCaseSensitive));
}
}
private void fillLookupArray() {
//reset lookup array
for (int i = 0; i < symbolLookup.length; i++) {
symbolLookup[i] = -1;
}
for (int i = 0; i < symbols.length(); i++) {
char c = symbols.charAt(i);
if (symbolLookup[(int) c] == -1) {
symbolLookup[(int) c] = i;
} else {
throw new IllegalArgumentException("duplicate symbol:" + c);
}
}
}
private static String makeAlphaNumericString(boolean caseSensitive) {
StringBuilder sb = new StringBuilder(255);
int caseDiff = 'a' - 'A';
for (int i = 'A'; i <= 'Z'; i++) {
sb.append((char) i);
if (caseSensitive) sb.append((char) (i + caseDiff));
}
for (int i = '0'; i <= '9'; i++) {
sb.append((char) i);
}
return sb.toString();
}
public String encodeNumber(long decNum) {
return encodeNumber(decNum, 0);
}
public String encodeNumber(long decNum, int minLen) {
StringBuilder result = new StringBuilder(20);
long num = decNum;
long mod = 0;
int base = symbols.length();
do {
mod = num % base;
result.append(symbols.charAt((int) mod));
num = Math.round(Math.floor((num-mod) / base));
} while (num > 0);
if (result.length() < minLen) {
for (int i = result.length(); i < minLen; i++) {
result.append(symbols.charAt(0));
}
}
return result.toString();
}
public long decodeNumber(String encNum) {
if (encNum == null) return 0;
if (!isCaseSensitive) encNum = encNum.toUpperCase();
long result = 0;
int base = symbols.length();
long multiplier = 1;
for (int i = 0; i < encNum.length(); i++) {
char c = encNum.charAt(i);
int pos = symbolLookup[(int) c];
if (pos == -1) {
String debugValue = encNum.substring(0, i) + "[" + c + "]";
if (encNum.length()-1 > i) {
debugValue += encNum.substring(i + 1);
}
throw new IllegalArgumentException(
"invalid symbol '" + c + "' at position "
+ (i+1) + ": " + debugValue);
} else {
result += pos * multiplier;
multiplier = multiplier * base;
}
}
return result;
}
#Override
public String toString() {
return symbols;
}
}
The test:
public class EncodeUtilTest {
#Test
public void testRoundTrip() throws Exception {
//for some reason, numbers larger than this range will not be decoded correctly
//maybe some bug in JVM with arithmetic with long values?
//tried also BigDecimal, didn't make any difference
//anyway, it is highly improbable that we ever need such large numbers
long value = 288230376151711743L;
test(value, new EncodeUtil());
test(value, new EncodeUtil(false));
test(value, new EncodeUtil(true, "1234567890qwertyuiopasdfghjklzxcvbnm"));
}
#Test
public void testRoundTripMax() throws Exception {
//this will fail, see above
test(Long.MAX_VALUE, new EncodeUtil());
}
#Test
public void testRoundTripGettingCloserToMax() throws Exception {
//here we test different values, getting closer to Long.MAX_VALUE
//this will fail, see above
EncodeUtil util = new EncodeUtil();
for (long i = 1000; i > 0; i--) {
System.out.println(i);
test(Long.MAX_VALUE / i, util);
}
}
private void test(long number, EncodeUtil util) throws Exception {
String encoded = util.encodeNumber(number);
long result = util.decodeNumber(encoded);
long diff = number - result;
//System.out.println(number + " = " + encoded + " diff " + diff);
assertEquals("original=" + number + ", result=" + result + ", encoded=" + encoded, 0, diff);
}
}
Any ideas why things start failing when the values get large? I also tried BigInteger, but it did not seem to make a difference.
You're using floating point maths in your encodeNumber method, which makes your code rely on the precision of the double type.
Replacing
num = Math.round(Math.floor((num-mod) / base));
with
num = (num - mod) / base;
Makes the tests pass. Actually
num = num / base;
Should work just as well (thought experiment: what is 19 / 10 when / is integer division?).
You have a conversion to double in your code, which could be generating strange results for large values.
num = Math.round(Math.floor((num-mod) / base));
that would be my first port of call.

Categories

Resources