Real.java
package calculator.atoms;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import calculator.Expression;
import calculator.IllegalConstruction;
import calculator.operations.Operation;
import calculator.atoms.visitor.AtomVisitor;
import calculator.functions.BinaryFunction;
import calculator.functions.UnaryFunction;
import visitor.Visitor;
/**
* Real is a concrete class that represents arithmetic (Real) numbers,
* which are Atoms, a special kind of Expressions.
*
* @see Expression
* @see Operation
*/
public class Real implements Atom {
public static int scale = 64;
public static MathContext context = new MathContext(scale + 1, RoundingMode.HALF_EVEN);
/*
* the actual Real value
* in case of a special real value it is used to determine which special real
* it represents
*/
private final BigDecimal value;
/*
* A boolean flag used to know if the Real is a special value
* if the flag is true, there is 3 possibilities :
* value = 1 => the Real represents +\inf
* value = -1 => the Real represents -\inf
* value = 0 => the Real represents a NaN
*/
private boolean special = false;
/**
* getter method to obtain the value contained in the object
*
* @return The integer number contained in the object
*/
public BigDecimal getValue() {
return value;
}
/**
* Constructor method for a string
*
* @param s The string to be represented in the Real
*/
public /* constructor */ Real(String s) {
BigDecimal temp = new BigDecimal(s, context);
value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
}
/**
* Constructor method for a BigDecimal
*
* @param d the BigDecimal to be represented in the Real
*/
public /* constructor */ Real(BigDecimal d) {
value = d.setScale(Real.scale, RoundingMode.HALF_EVEN);
}
/**
* Constructor method for a double
*
* @param d The double to be represented in the Real
*/
public /* constructor */ Real(double d) {
BigDecimal temp = BigDecimal.valueOf(d);
value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
}
/**
* Constructor method
*
* @param i The int value to be contained in the object
*/
public /* constructor */ Real(int i) {
BigDecimal temp = BigDecimal.valueOf(i);
value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
}
/**
* Constructor for special Reals
*
* @param v either 1
* @throws IllegalConstruction
*/
private /* constructor */ Real(boolean s, int v) {
BigDecimal temp = BigDecimal.valueOf(v);
value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
special = s;
}
/**
* Returns a NaN Real
*
* @return A new Real number representing a NaN
*/
public static Real nan() {
return new Real(true, 0);
};
/**
* Returns a Real representing +infinity
*
* @return A new Real number representing +infinity
*/
public static Real plusInf() {
return new Real(true, 1);
};
/**
* Returns a Real representing -infinity
*
* @return A new Real number representing -infinity
*/
public static Real minusInf() {
return new Real(true, -1);
};
/**
* Returns if the Real is representing -infinity
*
* @return if the Real is representing -infinity
*/
public boolean isMinusInf() {
return special && value.doubleValue() == -1;
}
/**
* Returns if the Real is representing +infinity
*
* @return if the Real is representing +infinity
*/
public boolean isPlusInf() {
return special && value.doubleValue() == 1;
}
/**
* Returns if the Real is representing NaN
*
* @return if the Real is representing NaN
*/
public boolean isNan() {
return special && value.doubleValue() == 0;
}
/**
* accept method to implement the visitor design pattern to traverse arithmetic
* expressions.
* Each real number will pass itself to the Atomvisitor object to get processed
* by the Atomvisitor.
*
* @param v The Atomvisitor object
*/
@Override
public void accept(AtomVisitor v) {
v.visit(this);
}
/**
* accept method to implement the visitor design pattern to traverse arithmetic
* expressions.
* Each real number will pass itself to the visitor object to get processed by
* the
* visitor.
*
* @param v The visitor object
*/
@Override
public void accept(Visitor v) {
v.visit(this);
}
/**
* Two Real expressions are equal if the values they contain are equal
*
* @param o The object to compare to
* @return A boolean representing the result of the equality test
*/
@Override
public boolean equals(Object o) {
// No object should be equal to null (not including this check can result in an
// exception if a Real is tested against null)
if (o == null)
return false;
// If the object is compared to itself then return true
if (o == this) {
return true;
}
// If the object is of another type then return false
if (!(o instanceof Real)) {
return false;
}
// return the equality between BigDecimals
return this.value.equals(((Real) o).getValue()) && special == ((Real) o).special;
// return this.value.compareTo(((Real) o).value) == 0;
}
/**
* The method hashCode needs to be overridden it the equals method is
* overridden;
* otherwise there may be problems when you use your object in hashed
* collections
* such as HashMap, HashSet, LinkedHashSet.
*
* @return The result of computing the hash.
*/
@Override
public int hashCode() {
return value.intValue();
}
/**
* applies an operation between two Reals
*
* @param o the operation to apply
* @param a the other Real
* @return The result of the application of o on a and this instance
*/
@Override
public Real apply(Operation o, Atom a) {
return o.op(this, (Real) a);
}
@Override
public Atom apply(BinaryFunction f, Atom a) {
return f.op(this, (Real) a);
}
@Override
public Real apply(UnaryFunction o) {
return o.op(this);
}
@Override
public String toString() { return value.stripTrailingZeros().toPlainString(); }
}