View Javadoc
1   
2   package calculator.atoms;
3   
4   import java.math.BigDecimal;
5   import java.math.MathContext;
6   import java.math.RoundingMode;
7   
8   import calculator.Expression;
9   import calculator.IllegalConstruction;
10  import calculator.operations.Operation;
11  import calculator.atoms.visitor.AtomVisitor;
12  import calculator.functions.BinaryFunction;
13  import calculator.functions.UnaryFunction;
14  import visitor.Visitor;
15  
16  /**
17   * Real is a concrete class that represents arithmetic (Real) numbers,
18   * which are Atoms, a special kind of Expressions.
19   *
20   * @see Expression
21   * @see Operation
22   */
23  public class Real implements Atom {
24  
25  	public static int scale = 64;
26  	public static MathContext context = new MathContext(scale + 1, RoundingMode.HALF_EVEN);
27  
28  	/*
29  	 * the actual Real value
30  	 * in case of a special real value it is used to determine which special real
31  	 * it represents
32  	 */
33  	private final BigDecimal value;
34  
35  	/*
36  	 * A boolean flag used to know if the Real is a special value
37  	 * if the flag is true, there is 3 possibilities :
38  	 * value = 1 => the Real represents +\inf
39  	 * value = -1 => the Real represents -\inf
40  	 * value = 0 => the Real represents a NaN
41  	 */
42  	private boolean special = false;
43  
44  	/**
45  	 * getter method to obtain the value contained in the object
46  	 *
47  	 * @return The integer number contained in the object
48  	 */
49  	public BigDecimal getValue() {
50  		return value;
51  	}
52  
53  	/**
54  	 * Constructor method for a string
55  	 *
56  	 * @param s The string to be represented in the Real
57  	 */
58  	public /* constructor */ Real(String s) {
59  		BigDecimal temp = new BigDecimal(s, context);
60  		value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
61  	}
62  
63  	/**
64  	 * Constructor method for a BigDecimal
65  	 *
66  	 * @param d the BigDecimal to be represented in the Real
67  	 */
68  	public /* constructor */ Real(BigDecimal d) {
69  		value = d.setScale(Real.scale, RoundingMode.HALF_EVEN);
70  	}
71  
72  	/**
73  	 * Constructor method for a double
74  	 *
75  	 * @param d The double to be represented in the Real
76  	 */
77  	public /* constructor */ Real(double d) {
78  		BigDecimal temp = BigDecimal.valueOf(d);
79  		value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
80  	}
81  
82  	/**
83  	 * Constructor method
84  	 *
85  	 * @param i The int value to be contained in the object
86  	 */
87  	public /* constructor */ Real(int i) {
88  		BigDecimal temp = BigDecimal.valueOf(i);
89  		value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
90  	}
91  
92  	/**
93  	 * Constructor for special Reals
94  	 *
95  	 * @param v either 1
96  	 * @throws IllegalConstruction
97  	 */
98  	private /* constructor */ Real(boolean s, int v) {
99  		BigDecimal temp = BigDecimal.valueOf(v);
100 		value = temp.setScale(Real.scale, RoundingMode.HALF_EVEN);
101 		special = s;
102 	}
103 
104 	/**
105 	 * Returns a NaN Real
106 	 * 
107 	 * @return A new Real number representing a NaN
108 	 */
109 	public static Real nan() {
110 		return new Real(true, 0);
111 	};
112 
113 	/**
114 	 * Returns a Real representing +infinity
115 	 * 
116 	 * @return A new Real number representing +infinity
117 	 */
118 	public static Real plusInf() {
119 		return new Real(true, 1);
120 	};
121 
122 	/**
123 	 * Returns a Real representing -infinity
124 	 * 
125 	 * @return A new Real number representing -infinity
126 	 */
127 	public static Real minusInf() {
128 		return new Real(true, -1);
129 	};
130 
131 	/**
132 	 * Returns if the Real is representing -infinity
133 	 * 
134 	 * @return if the Real is representing -infinity
135 	 */
136 	public boolean isMinusInf() {
137 		return special && value.doubleValue() == -1;
138 	}
139 
140 	/**
141 	 * Returns if the Real is representing +infinity
142 	 * 
143 	 * @return if the Real is representing +infinity
144 	 */
145 	public boolean isPlusInf() {
146 		return special && value.doubleValue() == 1;
147 	}
148 
149 	/**
150 	 * Returns if the Real is representing NaN
151 	 * 
152 	 * @return if the Real is representing NaN
153 	 */
154 	public boolean isNan() {
155 		return special && value.doubleValue() == 0;
156 	}
157 
158 	/**
159 	 * accept method to implement the visitor design pattern to traverse arithmetic
160 	 * expressions.
161 	 * Each real number will pass itself to the Atomvisitor object to get processed
162 	 * by the Atomvisitor.
163 	 * 
164 	 * @param v The Atomvisitor object
165 	 */
166 	@Override
167 	public void accept(AtomVisitor v) {
168 		v.visit(this);
169 	}
170 
171 	/**
172 	 * accept method to implement the visitor design pattern to traverse arithmetic
173 	 * expressions.
174 	 * Each real number will pass itself to the visitor object to get processed by
175 	 * the
176 	 * visitor.
177 	 *
178 	 * @param v The visitor object
179 	 */
180 	@Override
181 	public void accept(Visitor v) {
182 		v.visit(this);
183 	}
184 
185 	/**
186 	 * Two Real expressions are equal if the values they contain are equal
187 	 *
188 	 * @param o The object to compare to
189 	 * @return A boolean representing the result of the equality test
190 	 */
191 	@Override
192 	public boolean equals(Object o) {
193 		// No object should be equal to null (not including this check can result in an
194 		// exception if a Real is tested against null)
195 		if (o == null)
196 			return false;
197 
198 		// If the object is compared to itself then return true
199 		if (o == this) {
200 			return true;
201 		}
202 
203 		// If the object is of another type then return false
204 		if (!(o instanceof Real)) {
205 			return false;
206 		}
207 		// return the equality between BigDecimals
208 		return this.value.equals(((Real) o).getValue()) && special == ((Real) o).special;
209 		// return this.value.compareTo(((Real) o).value) == 0;
210 	}
211 
212 	/**
213 	 * The method hashCode needs to be overridden it the equals method is
214 	 * overridden;
215 	 * otherwise there may be problems when you use your object in hashed
216 	 * collections
217 	 * such as HashMap, HashSet, LinkedHashSet.
218 	 *
219 	 * @return The result of computing the hash.
220 	 */
221 	@Override
222 	public int hashCode() {
223 		return value.intValue();
224 	}
225 
226 	/**
227 	 * applies an operation between two Reals
228 	 *
229 	 * @param o the operation to apply
230 	 * @param a the other Real
231 	 * @return The result of the application of o on a and this instance
232 	 */
233 	@Override
234 	public Real apply(Operation o, Atom a) {
235 		return o.op(this, (Real) a);
236 	}
237 
238 	@Override
239 	public Atom apply(BinaryFunction f, Atom a) {
240 		return f.op(this, (Real) a);
241 	}
242 
243 	@Override
244 	public Real apply(UnaryFunction o) {
245 		return o.op(this);
246 	}
247 
248 	@Override
249 	public String toString() { return value.stripTrailingZeros().toPlainString(); }
250 }