blob: e7920d0c079882a196c5eb80349e80f1ffb4ce3f [file] [log] [blame]
Robert Griesemerf17cd882015-01-30 14:53:53 -08001// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package big
6
7import (
Robert Griesemer721d5892015-02-03 17:37:01 -08008 "math"
Robert Griesemerf17cd882015-01-30 14:53:53 -08009 "strconv"
10 "testing"
11)
12
Robert Griesemerf17cd882015-01-30 14:53:53 -080013func TestFloatSetFloat64String(t *testing.T) {
Robert Griesemerb8fcae02015-02-03 15:13:26 -080014 for _, test := range []struct {
15 s string
16 x float64
17 }{
Robert Griesemerd9859ad2015-02-13 17:57:26 -080018 // basics
Robert Griesemerb8fcae02015-02-03 15:13:26 -080019 {"0", 0},
20 {"-0", -0},
21 {"+0", 0},
22 {"1", 1},
23 {"-1", -1},
24 {"+1", 1},
25 {"1.234", 1.234},
26 {"-1.234", -1.234},
27 {"+1.234", 1.234},
28 {".1", 0.1},
29 {"1.", 1},
30 {"+1.", 1},
31
Robert Griesemerd9859ad2015-02-13 17:57:26 -080032 // various zeros
Robert Griesemerb8fcae02015-02-03 15:13:26 -080033 {"0e100", 0},
34 {"-0e+100", 0},
35 {"+0e-100", 0},
36 {"0E100", 0},
37 {"-0E+100", 0},
38 {"+0E-100", 0},
Robert Griesemerb8fcae02015-02-03 15:13:26 -080039
Robert Griesemerd9859ad2015-02-13 17:57:26 -080040 // various decimal exponent formats
Robert Griesemerb8fcae02015-02-03 15:13:26 -080041 {"1.e10", 1e10},
42 {"1e+10", 1e10},
43 {"+1e-10", 1e-10},
44 {"1E10", 1e10},
45 {"1.E+10", 1e10},
46 {"+1E-10", 1e-10},
Robert Griesemerb8fcae02015-02-03 15:13:26 -080047
Robert Griesemerd9859ad2015-02-13 17:57:26 -080048 // misc decimal values
49 {"3.14159265", 3.14159265},
Robert Griesemerb8fcae02015-02-03 15:13:26 -080050 {"-687436.79457e-245", -687436.79457e-245},
51 {"-687436.79457E245", -687436.79457e245},
Robert Griesemerb8fcae02015-02-03 15:13:26 -080052 {".0000000000000000000000000000000000000001", 1e-40},
53 {"+10000000000000000000000000000000000000000e-0", 1e40},
Robert Griesemerd9859ad2015-02-13 17:57:26 -080054
55 // decimal mantissa, binary exponent
56 {"0p0", 0},
57 {"-0p0", -0},
58 {"1p10", 1 << 10},
59 {"1p+10", 1 << 10},
60 {"+1p-10", 1.0 / (1 << 10)},
61 {"1024p-12", 0.25},
62 {"-1p10", -1024},
63 {"1.5p1", 3},
64
65 // binary mantissa, decimal exponent
66 {"0b0", 0},
67 {"-0b0", -0},
68 {"0b0e+10", 0},
69 {"-0b0e-10", -0},
70 {"0b1010", 10},
71 {"0B1010E2", 1000},
72 {"0b.1", 0.5},
73 {"0b.001", 0.125},
74 {"0b.001e3", 125},
75
76 // binary mantissa, binary exponent
77 {"0b0p+10", 0},
78 {"-0b0p-10", -0},
79 {"0b.1010p4", 10},
80 {"0b1p-1", 0.5},
81 {"0b001p-3", 0.125},
82 {"0b.001p3", 1},
83 {"0b0.01p2", 1},
84
85 // hexadecimal mantissa and exponent
86 {"0x0", 0},
87 {"-0x0", -0},
88 {"0x0p+10", 0},
89 {"-0x0p-10", -0},
90 {"0xff", 255},
91 {"0X.8p1", 1},
92 {"-0X0.00008p16", -0.5},
93 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
94 {"0x1.fffffffffffffp1023", math.MaxFloat64},
Robert Griesemerb8fcae02015-02-03 15:13:26 -080095 } {
Robert Griesemerf17cd882015-01-30 14:53:53 -080096 var x Float
Robert Griesemer6a10f722015-02-23 10:57:21 -080097 x.SetPrec(53)
Robert Griesemerf17cd882015-01-30 14:53:53 -080098 _, ok := x.SetString(test.s)
99 if !ok {
100 t.Errorf("%s: parse error", test.s)
101 continue
102 }
103 f, _ := x.Float64()
104 want := new(Float).SetFloat64(test.x)
105 if x.Cmp(want) != 0 {
106 t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
107 }
108 }
109}
110
Robert Griesemer721d5892015-02-03 17:37:01 -0800111const (
112 below1e23 = 99999999999999974834176
113 above1e23 = 100000000000000008388608
114)
115
116func TestFloat64Format(t *testing.T) {
Robert Griesemerf17cd882015-01-30 14:53:53 -0800117 for _, test := range []struct {
Robert Griesemer721d5892015-02-03 17:37:01 -0800118 x float64
Robert Griesemerf17cd882015-01-30 14:53:53 -0800119 format byte
120 prec int
121 want string
122 }{
Robert Griesemer721d5892015-02-03 17:37:01 -0800123 {0, 'f', 0, "0"},
124 {math.Copysign(0, -1), 'f', 0, "-0"},
125 {1, 'f', 0, "1"},
126 {-1, 'f', 0, "-1"},
Robert Griesemerf17cd882015-01-30 14:53:53 -0800127
Robert Griesemer721d5892015-02-03 17:37:01 -0800128 {1.459, 'e', 0, "1e+00"},
129 {2.459, 'e', 1, "2.5e+00"},
130 {3.459, 'e', 2, "3.46e+00"},
131 {4.459, 'e', 3, "4.459e+00"},
132 {5.459, 'e', 4, "5.4590e+00"},
133
134 {1.459, 'f', 0, "1"},
135 {2.459, 'f', 1, "2.5"},
136 {3.459, 'f', 2, "3.46"},
137 {4.459, 'f', 3, "4.459"},
138 {5.459, 'f', 4, "5.4590"},
139
140 {0, 'b', 0, "0"},
141 {math.Copysign(0, -1), 'b', 0, "-0"},
142 {1.0, 'b', 0, "4503599627370496p-52"},
143 {-1.0, 'b', 0, "-4503599627370496p-52"},
144 {4503599627370496, 'b', 0, "4503599627370496p+0"},
145
146 {0, 'p', 0, "0"},
147 {math.Copysign(0, -1), 'p', 0, "-0"},
148 {1024.0, 'p', 0, "0x.8p11"},
149 {-1024.0, 'p', 0, "-0x.8p11"},
150
151 // all test cases below from strconv/ftoa_test.go
152 {1, 'e', 5, "1.00000e+00"},
153 {1, 'f', 5, "1.00000"},
154 {1, 'g', 5, "1"},
155 // {1, 'g', -1, "1"},
156 // {20, 'g', -1, "20"},
157 // {1234567.8, 'g', -1, "1.2345678e+06"},
158 // {200000, 'g', -1, "200000"},
159 // {2000000, 'g', -1, "2e+06"},
160
161 // g conversion and zero suppression
162 {400, 'g', 2, "4e+02"},
163 {40, 'g', 2, "40"},
164 {4, 'g', 2, "4"},
165 {.4, 'g', 2, "0.4"},
166 {.04, 'g', 2, "0.04"},
167 {.004, 'g', 2, "0.004"},
168 {.0004, 'g', 2, "0.0004"},
169 {.00004, 'g', 2, "4e-05"},
170 {.000004, 'g', 2, "4e-06"},
171
172 {0, 'e', 5, "0.00000e+00"},
173 {0, 'f', 5, "0.00000"},
174 {0, 'g', 5, "0"},
175 // {0, 'g', -1, "0"},
176
177 {-1, 'e', 5, "-1.00000e+00"},
178 {-1, 'f', 5, "-1.00000"},
179 {-1, 'g', 5, "-1"},
180 // {-1, 'g', -1, "-1"},
181
182 {12, 'e', 5, "1.20000e+01"},
183 {12, 'f', 5, "12.00000"},
184 {12, 'g', 5, "12"},
185 // {12, 'g', -1, "12"},
186
187 {123456700, 'e', 5, "1.23457e+08"},
188 {123456700, 'f', 5, "123456700.00000"},
189 {123456700, 'g', 5, "1.2346e+08"},
190 // {123456700, 'g', -1, "1.234567e+08"},
191
192 {1.2345e6, 'e', 5, "1.23450e+06"},
193 {1.2345e6, 'f', 5, "1234500.00000"},
194 {1.2345e6, 'g', 5, "1.2345e+06"},
195
196 {1e23, 'e', 17, "9.99999999999999916e+22"},
197 {1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
198 {1e23, 'g', 17, "9.9999999999999992e+22"},
199
200 // {1e23, 'e', -1, "1e+23"},
201 // {1e23, 'f', -1, "100000000000000000000000"},
202 // {1e23, 'g', -1, "1e+23"},
203
204 {below1e23, 'e', 17, "9.99999999999999748e+22"},
205 {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800206 {below1e23, 'g', 17, "9.9999999999999975e+22"},
Robert Griesemer721d5892015-02-03 17:37:01 -0800207
208 // {below1e23, 'e', -1, "9.999999999999997e+22"},
209 // {below1e23, 'f', -1, "99999999999999970000000"},
210 // {below1e23, 'g', -1, "9.999999999999997e+22"},
211
212 {above1e23, 'e', 17, "1.00000000000000008e+23"},
213 {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
214 // {above1e23, 'g', 17, "1.0000000000000001e+23"},
215
216 // {above1e23, 'e', -1, "1.0000000000000001e+23"},
217 // {above1e23, 'f', -1, "100000000000000010000000"},
218 // {above1e23, 'g', -1, "1.0000000000000001e+23"},
219
220 // {fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
221 // {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
222
223 // {32, 'g', -1, "32"},
224 // {32, 'g', 0, "3e+01"},
225
226 // {100, 'x', -1, "%x"},
227
228 // {math.NaN(), 'g', -1, "NaN"},
229 // {-math.NaN(), 'g', -1, "NaN"},
Robert Griesemer15594df2015-02-05 17:21:48 -0800230 {math.Inf(0), 'g', -1, "+Inf"},
231 {math.Inf(-1), 'g', -1, "-Inf"},
232 {-math.Inf(0), 'g', -1, "-Inf"},
Robert Griesemer721d5892015-02-03 17:37:01 -0800233
234 {-1, 'b', -1, "-4503599627370496p-52"},
235
236 // fixed bugs
237 {0.9, 'f', 1, "0.9"},
238 {0.09, 'f', 1, "0.1"},
239 {0.0999, 'f', 1, "0.1"},
240 {0.05, 'f', 1, "0.1"},
241 {0.05, 'f', 0, "0"},
242 {0.5, 'f', 1, "0.5"},
243 {0.5, 'f', 0, "0"},
244 {1.5, 'f', 0, "2"},
245
246 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
247 // {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
248 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
249 // {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
250
251 // Issue 2625.
252 {383260575764816448, 'f', 0, "383260575764816448"},
253 // {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
Robert Griesemerf17cd882015-01-30 14:53:53 -0800254 } {
Robert Griesemer721d5892015-02-03 17:37:01 -0800255 f := new(Float).SetFloat64(test.x)
Robert Griesemerf17cd882015-01-30 14:53:53 -0800256 got := f.Format(test.format, test.prec)
257 if got != test.want {
Robert Griesemerb8fcae02015-02-03 15:13:26 -0800258 t.Errorf("%v: got %s; want %s", test, got, test.want)
Robert Griesemerf17cd882015-01-30 14:53:53 -0800259 }
Robert Griesemerb8fcae02015-02-03 15:13:26 -0800260
Robert Griesemer721d5892015-02-03 17:37:01 -0800261 if test.format == 'b' && test.x == 0 {
Robert Griesemerb8fcae02015-02-03 15:13:26 -0800262 continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
Robert Griesemerf17cd882015-01-30 14:53:53 -0800263 }
Robert Griesemerb8fcae02015-02-03 15:13:26 -0800264 if test.format == 'p' {
265 continue // 'p' format not supported in strconv.Format
266 }
267
268 // verify that Float format matches strconv format
Robert Griesemer721d5892015-02-03 17:37:01 -0800269 want := strconv.FormatFloat(test.x, test.format, test.prec, 64)
Robert Griesemerf17cd882015-01-30 14:53:53 -0800270 if got != want {
Robert Griesemer721d5892015-02-03 17:37:01 -0800271 t.Errorf("%v: got %s; want %s (strconv)", test, got, want)
Robert Griesemerf17cd882015-01-30 14:53:53 -0800272 }
273 }
274}
Robert Griesemer91c0f002015-02-04 16:31:59 -0800275
276func TestFloatFormat(t *testing.T) {
277 for _, test := range []struct {
278 x string
Robert Griesemerce137592015-02-23 13:15:10 -0800279 prec uint
Robert Griesemer91c0f002015-02-04 16:31:59 -0800280 format byte
Robert Griesemerce137592015-02-23 13:15:10 -0800281 digits int
Robert Griesemer91c0f002015-02-04 16:31:59 -0800282 want string
283 }{
Robert Griesemerce137592015-02-23 13:15:10 -0800284 {"0", 10, 'f', 0, "0"},
285 {"-0", 10, 'f', 0, "-0"},
286 {"1", 10, 'f', 0, "1"},
287 {"-1", 10, 'f', 0, "-1"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800288
Robert Griesemerce137592015-02-23 13:15:10 -0800289 {"1.459", 100, 'e', 0, "1e+00"},
290 {"2.459", 100, 'e', 1, "2.5e+00"},
291 {"3.459", 100, 'e', 2, "3.46e+00"},
292 {"4.459", 100, 'e', 3, "4.459e+00"},
293 {"5.459", 100, 'e', 4, "5.4590e+00"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800294
Robert Griesemerce137592015-02-23 13:15:10 -0800295 {"1.459", 100, 'E', 0, "1E+00"},
296 {"2.459", 100, 'E', 1, "2.5E+00"},
297 {"3.459", 100, 'E', 2, "3.46E+00"},
298 {"4.459", 100, 'E', 3, "4.459E+00"},
299 {"5.459", 100, 'E', 4, "5.4590E+00"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800300
Robert Griesemerce137592015-02-23 13:15:10 -0800301 {"1.459", 100, 'f', 0, "1"},
302 {"2.459", 100, 'f', 1, "2.5"},
303 {"3.459", 100, 'f', 2, "3.46"},
304 {"4.459", 100, 'f', 3, "4.459"},
305 {"5.459", 100, 'f', 4, "5.4590"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800306
Robert Griesemerce137592015-02-23 13:15:10 -0800307 {"1.459", 100, 'g', 0, "1"},
308 {"2.459", 100, 'g', 1, "2"},
309 {"3.459", 100, 'g', 2, "3.5"},
310 {"4.459", 100, 'g', 3, "4.46"},
311 {"5.459", 100, 'g', 4, "5.459"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800312
Robert Griesemerce137592015-02-23 13:15:10 -0800313 {"1459", 53, 'g', 0, "1e+03"},
314 {"2459", 53, 'g', 1, "2e+03"},
315 {"3459", 53, 'g', 2, "3.5e+03"},
316 {"4459", 53, 'g', 3, "4.46e+03"},
317 {"5459", 53, 'g', 4, "5459"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800318
Robert Griesemerce137592015-02-23 13:15:10 -0800319 {"1459", 53, 'G', 0, "1E+03"},
320 {"2459", 53, 'G', 1, "2E+03"},
321 {"3459", 53, 'G', 2, "3.5E+03"},
322 {"4459", 53, 'G', 3, "4.46E+03"},
323 {"5459", 53, 'G', 4, "5459"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800324
Robert Griesemerce137592015-02-23 13:15:10 -0800325 {"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
326 {"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
327 {"3", 10, 'g', 40, "3"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800328
Robert Griesemerce137592015-02-23 13:15:10 -0800329 {"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
330 {"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
331 {"3e40", 100, 'g', 40, "3e+40"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800332
333 // TODO(gri) need tests for actual large Floats
334
Robert Griesemerce137592015-02-23 13:15:10 -0800335 {"0", 53, 'b', 0, "0"},
336 {"-0", 53, 'b', 0, "-0"},
337 {"1.0", 53, 'b', 0, "4503599627370496p-52"},
338 {"-1.0", 53, 'b', 0, "-4503599627370496p-52"},
339 {"4503599627370496", 53, 'b', 0, "4503599627370496p+0"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800340
Robert Griesemerce137592015-02-23 13:15:10 -0800341 // issue 9939
342 {"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
343 {"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
344 {"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
345 {"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
346 {"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
347 {"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
348
349 {"3", 350, 'p', 0, "0x.cp2"},
350 {"03", 350, 'p', 0, "0x.cp2"},
351 {"3.", 350, 'p', 0, "0x.cp2"},
352 {"3.0", 350, 'p', 0, "0x.cp2"},
353 {"3.00", 350, 'p', 0, "0x.cp2"},
354 {"3.000", 350, 'p', 0, "0x.cp2"},
355
356 {"0", 64, 'p', 0, "0"},
357 {"-0", 64, 'p', 0, "-0"},
358 {"1024.0", 64, 'p', 0, "0x.8p11"},
359 {"-1024.0", 64, 'p', 0, "-0x.8p11"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800360
361 // unsupported format
Robert Griesemerce137592015-02-23 13:15:10 -0800362 {"3.14", 64, 'x', 0, "%x"},
Robert Griesemer91c0f002015-02-04 16:31:59 -0800363 } {
Robert Griesemerce137592015-02-23 13:15:10 -0800364 f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
Robert Griesemer6a10f722015-02-23 10:57:21 -0800365 if err != nil {
Robert Griesemer91c0f002015-02-04 16:31:59 -0800366 t.Errorf("%v: %s", test, err)
367 continue
368 }
369
Robert Griesemerce137592015-02-23 13:15:10 -0800370 got := f.Format(test.format, test.digits)
Robert Griesemer91c0f002015-02-04 16:31:59 -0800371 if got != test.want {
372 t.Errorf("%v: got %s; want %s", test, got, test.want)
373 }
Robert Griesemerce137592015-02-23 13:15:10 -0800374
375 // compare with strconv.FormatFloat output if possible
376 // ('p' format is not supported by strconv.FormatFloat,
377 // and its output for 0.0 prints a biased exponent value
378 // as in 0p-1074 which makes no sense to emulate here)
379 if test.prec == 53 && test.format != 'p' && f.Sign() != 0 {
Robert Griesemerd9859ad2015-02-13 17:57:26 -0800380 f64, acc := f.Float64()
381 if acc != Exact {
382 t.Errorf("%v: expected exact conversion to float64", test)
383 continue
384 }
Robert Griesemerce137592015-02-23 13:15:10 -0800385 got := strconv.FormatFloat(f64, test.format, test.digits, 64)
386 if got != test.want {
387 t.Errorf("%v: got %s; want %s", test, got, test.want)
388 }
389 }
Robert Griesemer91c0f002015-02-04 16:31:59 -0800390 }
391}