View Javadoc

1   package com.sharkysoft.math;
2   
3   import java.math.BigDecimal;
4   
5   /***
6    * Real value in scientific notation.
7    *
8    * <p><b>Details:</b> A <code>MantissaExponent</code> represents the base 10
9    * "scientific notation" of a real value.  Instances of this class are returned
10   * exclusively by <code>MathToolbox.toScientificNotation</code>.</p>
11   *
12   * @author Sharky
13   */
14  public final class MantissaExponent
15  {
16  
17  	/***
18  	 * Exponent value for NaN.
19  	 * 
20  	 * <p><b>Details:</b> If {@link #getMantissa()} for an instance of 
21  	 * <code>MantissaExponent</code> returns <code>null</code> and 
22  	 * {@link #getExponent()} for the same instance returns <code>NAN</code>, 
23  	 * then the instance represents the NaN value.</p>
24  	 */
25  	public static final int NAN = 0;
26  
27  	/***
28  	 * Exponent value for NaN.
29  	 * 
30  	 * <p><b>Details:</b> If {@link #getMantissa()} for an instance of 
31  	 * <code>MantissaExponent</code> returns <code>null</code> and 
32  	 * {@link #getExponent()} for the same instance returns <code>NEG_INF</code>, 
33  	 * then the instance represents negative infinity.</p>
34  	 */
35  	public static final int NEG_INF = -1;
36  
37  	/***
38  	 * Exponent value for NaN.
39  	 * 
40  	 * <p><b>Details:</b> If {@link #getMantissa()} for an instance of 
41  	 * <code>MantissaExponent</code> returns <code>null</code> and 
42  	 * {@link #getExponent()} for the same instance returns 
43  	 * <code>POS_INF</code>, then the instance represents positive infinity.</p>
44  	 */
45  	public static final int POS_INF = +1;
46  
47  	private static final BigDecimal gpBdNan = new BigDecimal(NAN);
48  
49  	private static final BigDecimal gpBdNegInf = new BigDecimal(NEG_INF);
50  
51  	private static final BigDecimal gpBdPosInf = new BigDecimal(POS_INF);
52  
53  	private static final BigDecimal gpBdPos10 = BigDecimal.valueOf(+10);
54  
55  	private static final BigDecimal gpBdNeg10 = BigDecimal.valueOf(-10);
56  
57  	private static final BigDecimal gpBdPos1 = BigDecimal.valueOf(+1);
58  
59  	private static final BigDecimal gpBdNeg1 = BigDecimal.valueOf(-1);
60  
61  	////////////////
62  	//            //
63  	//  Mantissa  //
64  	//            //
65  	////////////////
66  
67  	/***
68  	 * Mantissa.
69  	 *
70  	 * <p><b>Details:</b> Property <code>Mantissa</code> is the mantissa part of
71  	 * the scientific notation.</p>
72  	 *
73  	 * @see #getMantissa()
74  	 */
75  	protected final BigDecimal mpMantissa;
76  
77  	/***
78  	 * Retrieves Mantissa property.
79  	 *
80  	 * @return current value
81  	 *
82  	 * @see #mpMantissa
83  	 */
84  	public BigDecimal getMantissa()
85  	{
86  		return mpMantissa;
87  	}
88  
89  	////////////////
90  	//            //
91  	//  Exponent  //
92  	//            //
93  	////////////////
94  
95  	/***
96  	 * Exponent.
97  	 *
98  	 * <p><b>Details:</b> Property <code>Exponent</code> is the exponent part of
99  	 * the scientific notation.</p>
100 	 *
101 	 * @see #getExponent()
102 	 */
103 	protected final int mnExponent;
104 
105 	/***
106 	 * Retrieves Exponent property.
107 	 *
108 	 * @return current value
109 	 *
110 	 * @see #mnExponent
111 	 */
112 	public int getExponent()
113 	{
114 		return mnExponent;
115 	}
116 
117 	////////////////////
118 	//                //
119 	//  constructors  //
120 	//                //
121 	////////////////////
122 
123 	/***
124 	 * Computes mantissa and exponent.
125 	 *
126 	 * <p><b>Details:</b> This constructor computes the scientific notation
127 	 * mantissa and exponent of the supplied real value.</p>
128 	 *
129 	 * @param ipBig the real value
130 	 */
131 	MantissaExponent(BigDecimal ipBig)
132 	{
133 		// Recognize special signals for special values.
134 		if (ipBig == gpBdNan || ipBig == gpBdNegInf || ipBig == gpBdPosInf)
135 		{
136 			mpMantissa = null;
137 			mnExponent = ipBig.intValue();
138 			return;
139 		}
140 		int vnExponent = 0;
141 		switch (ipBig.signum())
142 		{
143 		case 1 :
144 			if (ipBig.compareTo(gpBdPos10) >= 0)
145 			{
146 				do
147 				{
148 					ipBig = ipBig.movePointLeft(1);
149 					++ vnExponent;
150 				}
151 				while (ipBig.compareTo(gpBdPos10) >= 0);
152 			}
153 			else if (ipBig.compareTo(gpBdPos1) < 0)
154 			{
155 				do
156 				{
157 					ipBig = ipBig.movePointRight(1);
158 					-- vnExponent;
159 				}
160 				while (ipBig.compareTo(gpBdPos1) < 0);
161 			}
162 			break;
163 		case -1 :
164 			if (ipBig.compareTo(gpBdNeg10) <= 0)
165 			{
166 				do
167 				{
168 					ipBig = ipBig.movePointLeft(1);
169 					++ vnExponent;
170 				}
171 				while (ipBig.compareTo(gpBdNeg10) <= 0);
172 			}
173 			else if (ipBig.compareTo(gpBdNeg1) > 0)
174 			{
175 				do
176 				{
177 					ipBig = ipBig.movePointRight(1);
178 					-- vnExponent;
179 				}
180 				while (ipBig.compareTo(gpBdNeg1) > 0);
181 			}
182 			break;
183 		}
184 		mpMantissa = ipBig;
185 		mnExponent = vnExponent;
186 	}
187 
188 	private static BigDecimal getBig(final float ifValue)
189 	{
190 		if (ifValue == Float.POSITIVE_INFINITY)
191 			return gpBdPosInf;
192 		if (ifValue == Float.NEGATIVE_INFINITY)
193 			return gpBdNegInf;
194 		if (Float.isNaN(ifValue))
195 			return gpBdNan;
196 		return new BigDecimal(ifValue);
197 	}
198 
199 	/***
200 	 * Computes mantissa and exponent.
201 	 *
202 	 * <p><b>Details:</b> This constructor computes the scientific notation
203 	 * mantissa and exponent of the supplied real value.</p>
204 	 *
205 	 * @param ifVal the real value
206 	 */
207 	MantissaExponent(final float ifVal)
208 	{
209 		this(getBig(ifVal));
210 	}
211 
212 	private static BigDecimal getBig(final double idValue)
213 	{
214 		if (idValue == Double.POSITIVE_INFINITY)
215 			return gpBdPosInf;
216 		if (idValue == Double.NEGATIVE_INFINITY)
217 			return gpBdNegInf;
218 		if (Double.isNaN(idValue))
219 			return gpBdNan;
220 		return new BigDecimal(idValue);
221 	}
222 
223 	/***
224 	 * Computes mantissa and exponent.
225 	 *
226 	 * <p><b>Details:</b> This constructor computes the scientific notation
227 	 * mantissa and exponent of the supplied real value.</p>
228 	 *
229 	 * @param idVal the real value
230 	 */
231 	MantissaExponent(double idVal)
232 	{
233 		this(getBig(idVal));
234 	}
235 
236 	/***
237 	 * Generates scientific notation string.
238 	 *
239 	 * <p><b>Details:</b> <code>toString</code> renders this real value to a
240 	 * string in scientific notation, using the format "Mantissa*10^Exponent".
241 	 * If this value is not rational (i.e., NaN or Infinite), then this method
242 	 * returns the same string as <code>Float.toString(float)</code> would for 
243 	 * these special values.</p>
244 	 *
245 	 * @return the string
246 	 */
247 	public String toString()
248 	{
249 		if (mpMantissa == gpBdNan)
250 			return Float.toString(Float.NaN);
251 		if (mpMantissa == gpBdNegInf)
252 			return Float.toString(Float.NEGATIVE_INFINITY);
253 		if (mpMantissa == gpBdPosInf)
254 			return Float.toString(Float.POSITIVE_INFINITY);
255 		return mpMantissa + "*10^" + mnExponent;
256 	}
257 
258 }
259