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