6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 4160406 4705734 4707389
27 * @summary Tests for Float.parseFloat method
28 */
29
30 public class ParseFloat {
31
32 private static void check(String val, float expected) {
33 float n = Float.parseFloat(val);
34 if (n != expected)
35 throw new RuntimeException("Float.parseFloat failed. String:" +
36 val + " Result:" + n);
37 }
38
39 private static void rudimentaryTest() {
40 check(new String(""+Float.MIN_VALUE), Float.MIN_VALUE);
41 check(new String(""+Float.MAX_VALUE), Float.MAX_VALUE);
42
43 check("10", (float) 10.0);
44 check("10.0", (float) 10.0);
45 check("10.01", (float) 10.01);
46
47 check("-10", (float) -10.0);
48 check("-10.00", (float) -10.0);
49 check("-10.01", (float) -10.01);
50 }
51
52 static String badStrings[] = {
53 "",
54 "+",
55 "-",
56 "+e",
57 "-e",
58 "+e170",
59 "-e170",
60
61 // Make sure intermediate white space is not deleted.
62 "1234 e10",
63 "-1234 e10",
64
65 // Control characters in the interior of a string are not legal
66 "1\u0007e1",
67 "1e\u00071",
68
69 // NaN and infinity can't have trailing type suffices or exponents
165
166 }
167
168 /*
169 * Throws an exception if <code>Input</code> is
170 * <code>exceptionalInput</code> and {@link Float.parseFloat
171 * parseFloat} does <em>not</em> throw an exception or if
172 * <code>Input</code> is not <code>exceptionalInput</code> and
173 * <code>parseFloat</code> throws an exception. This method does
174 * not attempt to test whether the string is converted to the
175 * proper value; just whether the input is accepted appropriately
176 * or not.
177 */
178 private static void testParsing(String [] input,
179 boolean exceptionalInput) {
180 for(int i = 0; i < input.length; i++) {
181 double d;
182
183 try {
184 d = Float.parseFloat(input[i]);
185 }
186 catch (NumberFormatException e) {
187 if (! exceptionalInput) {
188 throw new RuntimeException("Float.parseFloat rejected " +
189 "good string `" + input[i] +
190 "'.");
191 }
192 break;
193 }
194 if (exceptionalInput) {
195 throw new RuntimeException("Float.parseFloat accepted " +
196 "bad string `" + input[i] +
197 "'.");
198 }
199 }
200 }
201
202 public static void main(String[] args) throws Exception {
203 rudimentaryTest();
204
205 testParsing(goodStrings, false);
206 testParsing(paddedGoodStrings, false);
207 testParsing(badStrings, true);
208 testParsing(paddedBadStrings, true);
209 }
210 }
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 4160406 4705734 4707389 6358355 7032154
27 * @summary Tests for Float.parseFloat method
28 */
29
30 import java.math.BigDecimal;
31 import java.math.BigInteger;
32
33 public class ParseFloat {
34
35 private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
36
37 private static void fail(String val, float n) {
38 throw new RuntimeException("Float.parseFloat failed. String:" +
39 val + " Result:" + n);
40 }
41
42 private static void check(String val) {
43 float n = Float.parseFloat(val);
44 boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
45 float na = Math.abs(n);
46 String s = val.trim().toLowerCase();
47 switch (s.charAt(s.length() - 1)) {
48 case 'd':
49 case 'f':
50 s = s.substring(0, s.length() - 1);
51 break;
52 }
53 boolean isNegative = false;
54 if (s.charAt(0) == '+') {
55 s = s.substring(1);
56 } else if (s.charAt(0) == '-') {
57 s = s.substring(1);
58 isNegative = true;
59 }
60 if (s.equals("nan")) {
61 if (!Float.isNaN(n)) {
62 fail(val, n);
63 }
64 return;
65 }
66 if (Float.isNaN(n)) {
67 fail(val, n);
68 }
69 if (isNegativeN != isNegative)
70 fail(val, n);
71 if (s.equals("infinity")) {
72 if (na != Float.POSITIVE_INFINITY) {
73 fail(val, n);
74 }
75 return;
76 }
77 BigDecimal bd;
78 if (s.startsWith("0x")) {
79 s = s.substring(2);
80 int indP = s.indexOf('p');
81 long exp = Long.parseLong(s.substring(indP + 1));
82 int indD = s.indexOf('.');
83 String significand;
84 if (indD >= 0) {
85 significand = s.substring(0, indD) + s.substring(indD + 1, indP);
86 exp -= 4*(indP - indD - 1);
87 } else {
88 significand = s.substring(0, indP);
89 }
90 bd = new BigDecimal(new BigInteger(significand, 16));
91 if (exp >= 0) {
92 bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
93 } else {
94 bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
95 }
96 } else {
97 bd = new BigDecimal(s);
98 }
99 BigDecimal l, u;
100 if (Float.isInfinite(na)) {
101 l = new BigDecimal(Float.MAX_VALUE).add(new BigDecimal(Math.ulp(Float.MAX_VALUE)).multiply(HALF));
102 u = null;
103 } else {
104 l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(-Math.nextUp(-na))).multiply(HALF));
105 u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
106 }
107 int cmpL = bd.compareTo(l);
108 int cmpU = u != null ? bd.compareTo(u) : -1;
109 if ((Float.floatToIntBits(n) & 1) != 0) {
110 if (cmpL <= 0 || cmpU >= 0) {
111 fail(val, n);
112 }
113 } else {
114 if (cmpL < 0 || cmpU > 0) {
115 fail(val, n);
116 }
117 }
118 }
119
120 private static void check(String val, float expected) {
121 float n = Float.parseFloat(val);
122 if (n != expected)
123 fail(val, n);
124 check(val);
125 }
126
127 private static void rudimentaryTest() {
128 check(new String(""+Float.MIN_VALUE), Float.MIN_VALUE);
129 check(new String(""+Float.MAX_VALUE), Float.MAX_VALUE);
130
131 check("10", (float) 10.0);
132 check("10.0", (float) 10.0);
133 check("10.01", (float) 10.01);
134
135 check("-10", (float) -10.0);
136 check("-10.00", (float) -10.0);
137 check("-10.01", (float) -10.01);
138
139 // bug 6358355
140 check("144115196665790480", 0x1.000002p57f);
141 check("144115196665790481", 0x1.000002p57f);
142 check("0.050000002607703203", 0.05f);
143 check("0.050000002607703204", 0.05f);
144 check("0.050000002607703205", 0.05f);
145 check("0.050000002607703206", 0.05f);
146 check("0.050000002607703207", 0.05f);
147 check("0.050000002607703208", 0.05f);
148 check("0.050000002607703209", 0.050000004f);
149 }
150
151 static String badStrings[] = {
152 "",
153 "+",
154 "-",
155 "+e",
156 "-e",
157 "+e170",
158 "-e170",
159
160 // Make sure intermediate white space is not deleted.
161 "1234 e10",
162 "-1234 e10",
163
164 // Control characters in the interior of a string are not legal
165 "1\u0007e1",
166 "1e\u00071",
167
168 // NaN and infinity can't have trailing type suffices or exponents
264
265 }
266
267 /*
268 * Throws an exception if <code>Input</code> is
269 * <code>exceptionalInput</code> and {@link Float.parseFloat
270 * parseFloat} does <em>not</em> throw an exception or if
271 * <code>Input</code> is not <code>exceptionalInput</code> and
272 * <code>parseFloat</code> throws an exception. This method does
273 * not attempt to test whether the string is converted to the
274 * proper value; just whether the input is accepted appropriately
275 * or not.
276 */
277 private static void testParsing(String [] input,
278 boolean exceptionalInput) {
279 for(int i = 0; i < input.length; i++) {
280 double d;
281
282 try {
283 d = Float.parseFloat(input[i]);
284 check(input[i]);
285 }
286 catch (NumberFormatException e) {
287 if (! exceptionalInput) {
288 throw new RuntimeException("Float.parseFloat rejected " +
289 "good string `" + input[i] +
290 "'.");
291 }
292 break;
293 }
294 if (exceptionalInput) {
295 throw new RuntimeException("Float.parseFloat accepted " +
296 "bad string `" + input[i] +
297 "'.");
298 }
299 }
300 }
301
302 /**
303 * For each power of two, test at boundaries of
304 * region that should convert to that value.
305 */
306 private static void testPowers() {
307 for(int i = -149; i <= +127; i++) {
308 float f = Math.scalb(1.0f, i);
309 BigDecimal f_BD = new BigDecimal(f);
310
311 BigDecimal lowerBound = f_BD.subtract(new BigDecimal(Math.ulp(-Math.nextUp(-f))).multiply(HALF));
312 BigDecimal upperBound = f_BD.add(new BigDecimal(Math.ulp(f)).multiply(HALF));
313
314 check(lowerBound.toString());
315 check(upperBound.toString());
316 }
317 check(new BigDecimal(Float.MAX_VALUE).add(new BigDecimal(Math.ulp(Float.MAX_VALUE)).multiply(HALF)).toString());
318 }
319
320 public static void main(String[] args) throws Exception {
321 rudimentaryTest();
322
323 testParsing(goodStrings, false);
324 testParsing(paddedGoodStrings, false);
325 testParsing(badStrings, true);
326 testParsing(paddedBadStrings, true);
327
328 testPowers();
329 }
330 }
|