github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/math/big/floatconv_test.go (about) 1 // 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 5 package big 6 7 import ( 8 "bytes" 9 "fmt" 10 "math" 11 "strconv" 12 "testing" 13 ) 14 15 func TestFloatSetFloat64String(t *testing.T) { 16 inf := math.Inf(0) 17 nan := math.NaN() 18 19 for _, test := range []struct { 20 s string 21 x float64 // NaNs represent invalid inputs 22 }{ 23 // basics 24 {"0", 0}, 25 {"-0", -0}, 26 {"+0", 0}, 27 {"1", 1}, 28 {"-1", -1}, 29 {"+1", 1}, 30 {"1.234", 1.234}, 31 {"-1.234", -1.234}, 32 {"+1.234", 1.234}, 33 {".1", 0.1}, 34 {"1.", 1}, 35 {"+1.", 1}, 36 37 // various zeros 38 {"0e100", 0}, 39 {"-0e+100", 0}, 40 {"+0e-100", 0}, 41 {"0E100", 0}, 42 {"-0E+100", 0}, 43 {"+0E-100", 0}, 44 45 // various decimal exponent formats 46 {"1.e10", 1e10}, 47 {"1e+10", 1e10}, 48 {"+1e-10", 1e-10}, 49 {"1E10", 1e10}, 50 {"1.E+10", 1e10}, 51 {"+1E-10", 1e-10}, 52 53 // infinities 54 {"Inf", inf}, 55 {"+Inf", inf}, 56 {"-Inf", -inf}, 57 {"inf", inf}, 58 {"+inf", inf}, 59 {"-inf", -inf}, 60 61 // invalid numbers 62 {"", nan}, 63 {"-", nan}, 64 {"0x", nan}, 65 {"0e", nan}, 66 {"1.2ef", nan}, 67 {"2..3", nan}, 68 {"123..", nan}, 69 {"infinity", nan}, 70 {"foobar", nan}, 71 72 // misc decimal values 73 {"3.14159265", 3.14159265}, 74 {"-687436.79457e-245", -687436.79457e-245}, 75 {"-687436.79457E245", -687436.79457e245}, 76 {".0000000000000000000000000000000000000001", 1e-40}, 77 {"+10000000000000000000000000000000000000000e-0", 1e40}, 78 79 // decimal mantissa, binary exponent 80 {"0p0", 0}, 81 {"-0p0", -0}, 82 {"1p10", 1 << 10}, 83 {"1p+10", 1 << 10}, 84 {"+1p-10", 1.0 / (1 << 10)}, 85 {"1024p-12", 0.25}, 86 {"-1p10", -1024}, 87 {"1.5p1", 3}, 88 89 // binary mantissa, decimal exponent 90 {"0b0", 0}, 91 {"-0b0", -0}, 92 {"0b0e+10", 0}, 93 {"-0b0e-10", -0}, 94 {"0b1010", 10}, 95 {"0B1010E2", 1000}, 96 {"0b.1", 0.5}, 97 {"0b.001", 0.125}, 98 {"0b.001e3", 125}, 99 100 // binary mantissa, binary exponent 101 {"0b0p+10", 0}, 102 {"-0b0p-10", -0}, 103 {"0b.1010p4", 10}, 104 {"0b1p-1", 0.5}, 105 {"0b001p-3", 0.125}, 106 {"0b.001p3", 1}, 107 {"0b0.01p2", 1}, 108 109 // hexadecimal mantissa and exponent 110 {"0x0", 0}, 111 {"-0x0", -0}, 112 {"0x0p+10", 0}, 113 {"-0x0p-10", -0}, 114 {"0xff", 255}, 115 {"0X.8p1", 1}, 116 {"-0X0.00008p16", -0.5}, 117 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64}, 118 {"0x1.fffffffffffffp1023", math.MaxFloat64}, 119 } { 120 var x Float 121 x.SetPrec(53) 122 _, ok := x.SetString(test.s) 123 if math.IsNaN(test.x) { 124 // test.s is invalid 125 if ok { 126 t.Errorf("%s: want parse error", test.s) 127 } 128 continue 129 } 130 // test.s is valid 131 if !ok { 132 t.Errorf("%s: got parse error", test.s) 133 continue 134 } 135 f, _ := x.Float64() 136 want := new(Float).SetFloat64(test.x) 137 if x.Cmp(want) != 0 { 138 t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x) 139 } 140 } 141 } 142 143 func fdiv(a, b float64) float64 { return a / b } 144 145 const ( 146 below1e23 = 99999999999999974834176 147 above1e23 = 100000000000000008388608 148 ) 149 150 func TestFloat64Text(t *testing.T) { 151 for _, test := range []struct { 152 x float64 153 format byte 154 prec int 155 want string 156 }{ 157 {0, 'f', 0, "0"}, 158 {math.Copysign(0, -1), 'f', 0, "-0"}, 159 {1, 'f', 0, "1"}, 160 {-1, 'f', 0, "-1"}, 161 162 {0.001, 'e', 0, "1e-03"}, 163 {0.459, 'e', 0, "5e-01"}, 164 {1.459, 'e', 0, "1e+00"}, 165 {2.459, 'e', 1, "2.5e+00"}, 166 {3.459, 'e', 2, "3.46e+00"}, 167 {4.459, 'e', 3, "4.459e+00"}, 168 {5.459, 'e', 4, "5.4590e+00"}, 169 170 {0.001, 'f', 0, "0"}, 171 {0.459, 'f', 0, "0"}, 172 {1.459, 'f', 0, "1"}, 173 {2.459, 'f', 1, "2.5"}, 174 {3.459, 'f', 2, "3.46"}, 175 {4.459, 'f', 3, "4.459"}, 176 {5.459, 'f', 4, "5.4590"}, 177 178 {0, 'b', 0, "0"}, 179 {math.Copysign(0, -1), 'b', 0, "-0"}, 180 {1.0, 'b', 0, "4503599627370496p-52"}, 181 {-1.0, 'b', 0, "-4503599627370496p-52"}, 182 {4503599627370496, 'b', 0, "4503599627370496p+0"}, 183 184 {0, 'p', 0, "0"}, 185 {math.Copysign(0, -1), 'p', 0, "-0"}, 186 {1024.0, 'p', 0, "0x.8p+11"}, 187 {-1024.0, 'p', 0, "-0x.8p+11"}, 188 189 // all test cases below from strconv/ftoa_test.go 190 {1, 'e', 5, "1.00000e+00"}, 191 {1, 'f', 5, "1.00000"}, 192 {1, 'g', 5, "1"}, 193 {1, 'g', -1, "1"}, 194 {20, 'g', -1, "20"}, 195 {1234567.8, 'g', -1, "1.2345678e+06"}, 196 {200000, 'g', -1, "200000"}, 197 {2000000, 'g', -1, "2e+06"}, 198 199 // g conversion and zero suppression 200 {400, 'g', 2, "4e+02"}, 201 {40, 'g', 2, "40"}, 202 {4, 'g', 2, "4"}, 203 {.4, 'g', 2, "0.4"}, 204 {.04, 'g', 2, "0.04"}, 205 {.004, 'g', 2, "0.004"}, 206 {.0004, 'g', 2, "0.0004"}, 207 {.00004, 'g', 2, "4e-05"}, 208 {.000004, 'g', 2, "4e-06"}, 209 210 {0, 'e', 5, "0.00000e+00"}, 211 {0, 'f', 5, "0.00000"}, 212 {0, 'g', 5, "0"}, 213 {0, 'g', -1, "0"}, 214 215 {-1, 'e', 5, "-1.00000e+00"}, 216 {-1, 'f', 5, "-1.00000"}, 217 {-1, 'g', 5, "-1"}, 218 {-1, 'g', -1, "-1"}, 219 220 {12, 'e', 5, "1.20000e+01"}, 221 {12, 'f', 5, "12.00000"}, 222 {12, 'g', 5, "12"}, 223 {12, 'g', -1, "12"}, 224 225 {123456700, 'e', 5, "1.23457e+08"}, 226 {123456700, 'f', 5, "123456700.00000"}, 227 {123456700, 'g', 5, "1.2346e+08"}, 228 {123456700, 'g', -1, "1.234567e+08"}, 229 230 {1.2345e6, 'e', 5, "1.23450e+06"}, 231 {1.2345e6, 'f', 5, "1234500.00000"}, 232 {1.2345e6, 'g', 5, "1.2345e+06"}, 233 234 {1e23, 'e', 17, "9.99999999999999916e+22"}, 235 {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, 236 {1e23, 'g', 17, "9.9999999999999992e+22"}, 237 238 {1e23, 'e', -1, "1e+23"}, 239 {1e23, 'f', -1, "100000000000000000000000"}, 240 {1e23, 'g', -1, "1e+23"}, 241 242 {below1e23, 'e', 17, "9.99999999999999748e+22"}, 243 {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"}, 244 {below1e23, 'g', 17, "9.9999999999999975e+22"}, 245 246 {below1e23, 'e', -1, "9.999999999999997e+22"}, 247 {below1e23, 'f', -1, "99999999999999970000000"}, 248 {below1e23, 'g', -1, "9.999999999999997e+22"}, 249 250 {above1e23, 'e', 17, "1.00000000000000008e+23"}, 251 {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"}, 252 {above1e23, 'g', 17, "1.0000000000000001e+23"}, 253 254 {above1e23, 'e', -1, "1.0000000000000001e+23"}, 255 {above1e23, 'f', -1, "100000000000000010000000"}, 256 {above1e23, 'g', -1, "1.0000000000000001e+23"}, 257 258 {5e-304 / 1e20, 'g', -1, "5e-324"}, 259 {-5e-304 / 1e20, 'g', -1, "-5e-324"}, 260 {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic 261 {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic 262 263 {32, 'g', -1, "32"}, 264 {32, 'g', 0, "3e+01"}, 265 266 {100, 'x', -1, "%x"}, 267 268 // {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs 269 // {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs 270 {math.Inf(0), 'g', -1, "+Inf"}, 271 {math.Inf(-1), 'g', -1, "-Inf"}, 272 {-math.Inf(0), 'g', -1, "-Inf"}, 273 274 {-1, 'b', -1, "-4503599627370496p-52"}, 275 276 // fixed bugs 277 {0.9, 'f', 1, "0.9"}, 278 {0.09, 'f', 1, "0.1"}, 279 {0.0999, 'f', 1, "0.1"}, 280 {0.05, 'f', 1, "0.1"}, 281 {0.05, 'f', 0, "0"}, 282 {0.5, 'f', 1, "0.5"}, 283 {0.5, 'f', 0, "0"}, 284 {1.5, 'f', 0, "2"}, 285 286 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 287 {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, 288 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 289 {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, 290 291 // Issue 2625. 292 {383260575764816448, 'f', 0, "383260575764816448"}, 293 {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, 294 295 // Issue 15918. 296 {1, 'f', -10, "1"}, 297 {1, 'f', -11, "1"}, 298 {1, 'f', -12, "1"}, 299 } { 300 // The test cases are from the strconv package which tests float64 values. 301 // When formatting values with prec = -1 (shortest representation), 302 // the actually available mantissa precision matters. 303 // For denormalized values, that precision is < 53 (SetFloat64 default). 304 // Compute and set the actual precision explicitly. 305 f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x) 306 got := f.Text(test.format, test.prec) 307 if got != test.want { 308 t.Errorf("%v: got %s; want %s", test, got, test.want) 309 continue 310 } 311 312 if test.format == 'b' && test.x == 0 { 313 continue // 'b' format in strconv.Float requires knowledge of bias for 0.0 314 } 315 if test.format == 'p' { 316 continue // 'p' format not supported in strconv.Format 317 } 318 319 // verify that Float format matches strconv format 320 want := strconv.FormatFloat(test.x, test.format, test.prec, 64) 321 if got != want { 322 t.Errorf("%v: got %s; want %s (strconv)", test, got, want) 323 } 324 } 325 } 326 327 // actualPrec returns the number of actually used mantissa bits. 328 func actualPrec(x float64) uint { 329 if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 { 330 // x is denormalized 331 return 64 - nlz64(bits&(1<<52-1)) 332 } 333 return 53 334 } 335 336 func TestFloatText(t *testing.T) { 337 for _, test := range []struct { 338 x string 339 prec uint 340 format byte 341 digits int 342 want string 343 }{ 344 {"0", 10, 'f', 0, "0"}, 345 {"-0", 10, 'f', 0, "-0"}, 346 {"1", 10, 'f', 0, "1"}, 347 {"-1", 10, 'f', 0, "-1"}, 348 349 {"1.459", 100, 'e', 0, "1e+00"}, 350 {"2.459", 100, 'e', 1, "2.5e+00"}, 351 {"3.459", 100, 'e', 2, "3.46e+00"}, 352 {"4.459", 100, 'e', 3, "4.459e+00"}, 353 {"5.459", 100, 'e', 4, "5.4590e+00"}, 354 355 {"1.459", 100, 'E', 0, "1E+00"}, 356 {"2.459", 100, 'E', 1, "2.5E+00"}, 357 {"3.459", 100, 'E', 2, "3.46E+00"}, 358 {"4.459", 100, 'E', 3, "4.459E+00"}, 359 {"5.459", 100, 'E', 4, "5.4590E+00"}, 360 361 {"1.459", 100, 'f', 0, "1"}, 362 {"2.459", 100, 'f', 1, "2.5"}, 363 {"3.459", 100, 'f', 2, "3.46"}, 364 {"4.459", 100, 'f', 3, "4.459"}, 365 {"5.459", 100, 'f', 4, "5.4590"}, 366 367 {"1.459", 100, 'g', 0, "1"}, 368 {"2.459", 100, 'g', 1, "2"}, 369 {"3.459", 100, 'g', 2, "3.5"}, 370 {"4.459", 100, 'g', 3, "4.46"}, 371 {"5.459", 100, 'g', 4, "5.459"}, 372 373 {"1459", 53, 'g', 0, "1e+03"}, 374 {"2459", 53, 'g', 1, "2e+03"}, 375 {"3459", 53, 'g', 2, "3.5e+03"}, 376 {"4459", 53, 'g', 3, "4.46e+03"}, 377 {"5459", 53, 'g', 4, "5459"}, 378 379 {"1459", 53, 'G', 0, "1E+03"}, 380 {"2459", 53, 'G', 1, "2E+03"}, 381 {"3459", 53, 'G', 2, "3.5E+03"}, 382 {"4459", 53, 'G', 3, "4.46E+03"}, 383 {"5459", 53, 'G', 4, "5459"}, 384 385 {"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"}, 386 {"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"}, 387 {"3", 10, 'g', 40, "3"}, 388 389 {"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"}, 390 {"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"}, 391 {"3e40", 100, 'g', 40, "3e+40"}, 392 393 // make sure "stupid" exponents don't stall the machine 394 {"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"}, 395 {"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"}, 396 {"1e646456993", 64, 'p', 0, "+Inf"}, 397 {"1e1000000000", 64, 'p', 0, "+Inf"}, 398 {"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"}, 399 {"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"}, 400 {"1e-646456994", 64, 'p', 0, "0"}, 401 {"1e-1000000000", 64, 'p', 0, "0"}, 402 403 // minimum and maximum values 404 {"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"}, 405 {"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"}, 406 {"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"}, 407 {"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"}, 408 409 // TODO(gri) need tests for actual large Floats 410 411 {"0", 53, 'b', 0, "0"}, 412 {"-0", 53, 'b', 0, "-0"}, 413 {"1.0", 53, 'b', 0, "4503599627370496p-52"}, 414 {"-1.0", 53, 'b', 0, "-4503599627370496p-52"}, 415 {"4503599627370496", 53, 'b', 0, "4503599627370496p+0"}, 416 417 // issue 9939 418 {"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 419 {"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 420 {"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 421 {"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 422 {"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 423 {"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 424 425 {"3", 350, 'p', 0, "0x.cp+2"}, 426 {"03", 350, 'p', 0, "0x.cp+2"}, 427 {"3.", 350, 'p', 0, "0x.cp+2"}, 428 {"3.0", 350, 'p', 0, "0x.cp+2"}, 429 {"3.00", 350, 'p', 0, "0x.cp+2"}, 430 {"3.000", 350, 'p', 0, "0x.cp+2"}, 431 432 {"0", 64, 'p', 0, "0"}, 433 {"-0", 64, 'p', 0, "-0"}, 434 {"1024.0", 64, 'p', 0, "0x.8p+11"}, 435 {"-1024.0", 64, 'p', 0, "-0x.8p+11"}, 436 437 // unsupported format 438 {"3.14", 64, 'x', 0, "%x"}, 439 {"-3.14", 64, 'x', 0, "%x"}, 440 } { 441 f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven) 442 if err != nil { 443 t.Errorf("%v: %s", test, err) 444 continue 445 } 446 447 got := f.Text(test.format, test.digits) 448 if got != test.want { 449 t.Errorf("%v: got %s; want %s", test, got, test.want) 450 } 451 452 // compare with strconv.FormatFloat output if possible 453 // ('p' format is not supported by strconv.FormatFloat, 454 // and its output for 0.0 prints a biased exponent value 455 // as in 0p-1074 which makes no sense to emulate here) 456 if test.prec == 53 && test.format != 'p' && f.Sign() != 0 { 457 f64, acc := f.Float64() 458 if acc != Exact { 459 t.Errorf("%v: expected exact conversion to float64", test) 460 continue 461 } 462 got := strconv.FormatFloat(f64, test.format, test.digits, 64) 463 if got != test.want { 464 t.Errorf("%v: got %s; want %s", test, got, test.want) 465 } 466 } 467 } 468 } 469 470 func TestFloatFormat(t *testing.T) { 471 for _, test := range []struct { 472 format string 473 value interface{} // float32, float64, or string (== 512bit *Float) 474 want string 475 }{ 476 // from fmt/fmt_test.go 477 {"%+.3e", 0.0, "+0.000e+00"}, 478 {"%+.3e", 1.0, "+1.000e+00"}, 479 {"%+.3f", -1.0, "-1.000"}, 480 {"%+.3F", -1.0, "-1.000"}, 481 {"%+.3F", float32(-1.0), "-1.000"}, 482 {"%+07.2f", 1.0, "+001.00"}, 483 {"%+07.2f", -1.0, "-001.00"}, 484 {"%+10.2f", +1.0, " +1.00"}, 485 {"%+10.2f", -1.0, " -1.00"}, 486 {"% .3E", -1.0, "-1.000E+00"}, 487 {"% .3e", 1.0, " 1.000e+00"}, 488 {"%+.3g", 0.0, "+0"}, 489 {"%+.3g", 1.0, "+1"}, 490 {"%+.3g", -1.0, "-1"}, 491 {"% .3g", -1.0, "-1"}, 492 {"% .3g", 1.0, " 1"}, 493 {"%b", float32(1.0), "8388608p-23"}, 494 {"%b", 1.0, "4503599627370496p-52"}, 495 496 // from fmt/fmt_test.go: old test/fmt_test.go 497 {"%e", 1.0, "1.000000e+00"}, 498 {"%e", 1234.5678e3, "1.234568e+06"}, 499 {"%e", 1234.5678e-8, "1.234568e-05"}, 500 {"%e", -7.0, "-7.000000e+00"}, 501 {"%e", -1e-9, "-1.000000e-09"}, 502 {"%f", 1234.5678e3, "1234567.800000"}, 503 {"%f", 1234.5678e-8, "0.000012"}, 504 {"%f", -7.0, "-7.000000"}, 505 {"%f", -1e-9, "-0.000000"}, 506 {"%g", 1234.5678e3, "1.2345678e+06"}, 507 {"%g", float32(1234.5678e3), "1.2345678e+06"}, 508 {"%g", 1234.5678e-8, "1.2345678e-05"}, 509 {"%g", -7.0, "-7"}, 510 {"%g", -1e-9, "-1e-09"}, 511 {"%g", float32(-1e-9), "-1e-09"}, 512 {"%E", 1.0, "1.000000E+00"}, 513 {"%E", 1234.5678e3, "1.234568E+06"}, 514 {"%E", 1234.5678e-8, "1.234568E-05"}, 515 {"%E", -7.0, "-7.000000E+00"}, 516 {"%E", -1e-9, "-1.000000E-09"}, 517 {"%G", 1234.5678e3, "1.2345678E+06"}, 518 {"%G", float32(1234.5678e3), "1.2345678E+06"}, 519 {"%G", 1234.5678e-8, "1.2345678E-05"}, 520 {"%G", -7.0, "-7"}, 521 {"%G", -1e-9, "-1E-09"}, 522 {"%G", float32(-1e-9), "-1E-09"}, 523 524 {"%20.6e", 1.2345e3, " 1.234500e+03"}, 525 {"%20.6e", 1.2345e-3, " 1.234500e-03"}, 526 {"%20e", 1.2345e3, " 1.234500e+03"}, 527 {"%20e", 1.2345e-3, " 1.234500e-03"}, 528 {"%20.8e", 1.2345e3, " 1.23450000e+03"}, 529 {"%20f", 1.23456789e3, " 1234.567890"}, 530 {"%20f", 1.23456789e-3, " 0.001235"}, 531 {"%20f", 12345678901.23456789, " 12345678901.234568"}, 532 {"%-20f", 1.23456789e3, "1234.567890 "}, 533 {"%20.8f", 1.23456789e3, " 1234.56789000"}, 534 {"%20.8f", 1.23456789e-3, " 0.00123457"}, 535 {"%g", 1.23456789e3, "1234.56789"}, 536 {"%g", 1.23456789e-3, "0.00123456789"}, 537 {"%g", 1.23456789e20, "1.23456789e+20"}, 538 {"%20e", math.Inf(1), " +Inf"}, 539 {"%-20f", math.Inf(-1), "-Inf "}, 540 541 // from fmt/fmt_test.go: comparison of padding rules with C printf 542 {"%.2f", 1.0, "1.00"}, 543 {"%.2f", -1.0, "-1.00"}, 544 {"% .2f", 1.0, " 1.00"}, 545 {"% .2f", -1.0, "-1.00"}, 546 {"%+.2f", 1.0, "+1.00"}, 547 {"%+.2f", -1.0, "-1.00"}, 548 {"%7.2f", 1.0, " 1.00"}, 549 {"%7.2f", -1.0, " -1.00"}, 550 {"% 7.2f", 1.0, " 1.00"}, 551 {"% 7.2f", -1.0, " -1.00"}, 552 {"%+7.2f", 1.0, " +1.00"}, 553 {"%+7.2f", -1.0, " -1.00"}, 554 {"%07.2f", 1.0, "0001.00"}, 555 {"%07.2f", -1.0, "-001.00"}, 556 {"% 07.2f", 1.0, " 001.00"}, 557 {"% 07.2f", -1.0, "-001.00"}, 558 {"%+07.2f", 1.0, "+001.00"}, 559 {"%+07.2f", -1.0, "-001.00"}, 560 561 // from fmt/fmt_test.go: zero padding does not apply to infinities 562 {"%020f", math.Inf(-1), " -Inf"}, 563 {"%020f", math.Inf(+1), " +Inf"}, 564 {"% 020f", math.Inf(-1), " -Inf"}, 565 {"% 020f", math.Inf(+1), " Inf"}, 566 {"%+020f", math.Inf(-1), " -Inf"}, 567 {"%+020f", math.Inf(+1), " +Inf"}, 568 {"%20f", -1.0, " -1.000000"}, 569 570 // handle %v like %g 571 {"%v", 0.0, "0"}, 572 {"%v", -7.0, "-7"}, 573 {"%v", -1e-9, "-1e-09"}, 574 {"%v", float32(-1e-9), "-1e-09"}, 575 {"%010v", 0.0, "0000000000"}, 576 577 // *Float cases 578 {"%.20f", "1e-20", "0.00000000000000000001"}, 579 {"%.20f", "-1e-20", "-0.00000000000000000001"}, 580 {"%30.20f", "-1e-20", " -0.00000000000000000001"}, 581 {"%030.20f", "-1e-20", "-00000000.00000000000000000001"}, 582 {"%030.20f", "+1e-20", "000000000.00000000000000000001"}, 583 {"% 030.20f", "+1e-20", " 00000000.00000000000000000001"}, 584 585 // erroneous formats 586 {"%s", 1.0, "%!s(*big.Float=1)"}, 587 } { 588 value := new(Float) 589 switch v := test.value.(type) { 590 case float32: 591 value.SetPrec(24).SetFloat64(float64(v)) 592 case float64: 593 value.SetPrec(53).SetFloat64(v) 594 case string: 595 value.SetPrec(512).Parse(v, 0) 596 default: 597 t.Fatalf("unsupported test value: %v (%T)", v, v) 598 } 599 600 if got := fmt.Sprintf(test.format, value); got != test.want { 601 t.Errorf("%v: got %q; want %q", test, got, test.want) 602 } 603 } 604 } 605 606 func BenchmarkParseFloatSmallExp(b *testing.B) { 607 for i := 0; i < b.N; i++ { 608 for _, s := range []string{ 609 "1e0", 610 "1e-1", 611 "1e-2", 612 "1e-3", 613 "1e-4", 614 "1e-5", 615 "1e-10", 616 "1e-20", 617 "1e-50", 618 "1e1", 619 "1e2", 620 "1e3", 621 "1e4", 622 "1e5", 623 "1e10", 624 "1e20", 625 "1e50", 626 } { 627 var x Float 628 _, _, err := x.Parse(s, 0) 629 if err != nil { 630 b.Fatalf("%s: %v", s, err) 631 } 632 } 633 } 634 } 635 636 func BenchmarkParseFloatLargeExp(b *testing.B) { 637 for i := 0; i < b.N; i++ { 638 for _, s := range []string{ 639 "1e0", 640 "1e-10", 641 "1e-20", 642 "1e-30", 643 "1e-40", 644 "1e-50", 645 "1e-100", 646 "1e-500", 647 "1e-1000", 648 "1e-5000", 649 "1e-10000", 650 "1e10", 651 "1e20", 652 "1e30", 653 "1e40", 654 "1e50", 655 "1e100", 656 "1e500", 657 "1e1000", 658 "1e5000", 659 "1e10000", 660 } { 661 var x Float 662 _, _, err := x.Parse(s, 0) 663 if err != nil { 664 b.Fatalf("%s: %v", s, err) 665 } 666 } 667 } 668 } 669 670 func TestFloatScan(t *testing.T) { 671 var floatScanTests = []struct { 672 input string 673 format string 674 output string 675 remaining int 676 wantErr bool 677 }{ 678 0: {"10.0", "%f", "10", 0, false}, 679 1: {"23.98+2.0", "%v", "23.98", 4, false}, 680 2: {"-1+1", "%v", "-1", 2, false}, 681 3: {" 00000", "%v", "0", 0, false}, 682 4: {"-123456p-78", "%b", "-4.084816388e-19", 0, false}, 683 5: {"+123", "%b", "123", 0, false}, 684 6: {"-1.234e+56", "%e", "-1.234e+56", 0, false}, 685 7: {"-1.234E-56", "%E", "-1.234e-56", 0, false}, 686 8: {"-1.234e+567", "%g", "-1.234e+567", 0, false}, 687 9: {"+1234567891011.234", "%G", "1.234567891e+12", 0, false}, 688 689 // Scan doesn't handle ±Inf. 690 10: {"Inf", "%v", "", 3, true}, 691 11: {"-Inf", "%v", "", 3, true}, 692 12: {"-Inf", "%v", "", 3, true}, 693 } 694 695 var buf bytes.Buffer 696 for i, test := range floatScanTests { 697 x := new(Float) 698 buf.Reset() 699 buf.WriteString(test.input) 700 _, err := fmt.Fscanf(&buf, test.format, x) 701 if test.wantErr { 702 if err == nil { 703 t.Errorf("#%d want non-nil err", i) 704 } 705 continue 706 } 707 708 if err != nil { 709 t.Errorf("#%d error: %s", i, err) 710 } 711 712 if x.String() != test.output { 713 t.Errorf("#%d got %s; want %s", i, x.String(), test.output) 714 } 715 if buf.Len() != test.remaining { 716 t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining) 717 } 718 } 719 }