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