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
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
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
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
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