github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/big/floatconv_test.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/big/floatconv_test.go 2 3 // Copyright 2015 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package big 8 9 import ( 10 "math" 11 "strconv" 12 "testing" 13 ) 14 15 func TestFloatSetFloat64String(t *testing.T) { 16 for _, test := range []struct { 17 s string 18 x float64 19 }{ 20 // basics 21 {"0", 0}, 22 {"-0", -0}, 23 {"+0", 0}, 24 {"1", 1}, 25 {"-1", -1}, 26 {"+1", 1}, 27 {"1.234", 1.234}, 28 {"-1.234", -1.234}, 29 {"+1.234", 1.234}, 30 {".1", 0.1}, 31 {"1.", 1}, 32 {"+1.", 1}, 33 34 // various zeros 35 {"0e100", 0}, 36 {"-0e+100", 0}, 37 {"+0e-100", 0}, 38 {"0E100", 0}, 39 {"-0E+100", 0}, 40 {"+0E-100", 0}, 41 42 // various decimal exponent formats 43 {"1.e10", 1e10}, 44 {"1e+10", 1e10}, 45 {"+1e-10", 1e-10}, 46 {"1E10", 1e10}, 47 {"1.E+10", 1e10}, 48 {"+1E-10", 1e-10}, 49 50 // misc decimal values 51 {"3.14159265", 3.14159265}, 52 {"-687436.79457e-245", -687436.79457e-245}, 53 {"-687436.79457E245", -687436.79457e245}, 54 {".0000000000000000000000000000000000000001", 1e-40}, 55 {"+10000000000000000000000000000000000000000e-0", 1e40}, 56 57 // decimal mantissa, binary exponent 58 {"0p0", 0}, 59 {"-0p0", -0}, 60 {"1p10", 1 << 10}, 61 {"1p+10", 1 << 10}, 62 {"+1p-10", 1.0 / (1 << 10)}, 63 {"1024p-12", 0.25}, 64 {"-1p10", -1024}, 65 {"1.5p1", 3}, 66 67 // binary mantissa, decimal exponent 68 {"0b0", 0}, 69 {"-0b0", -0}, 70 {"0b0e+10", 0}, 71 {"-0b0e-10", -0}, 72 {"0b1010", 10}, 73 {"0B1010E2", 1000}, 74 {"0b.1", 0.5}, 75 {"0b.001", 0.125}, 76 {"0b.001e3", 125}, 77 78 // binary mantissa, binary exponent 79 {"0b0p+10", 0}, 80 {"-0b0p-10", -0}, 81 {"0b.1010p4", 10}, 82 {"0b1p-1", 0.5}, 83 {"0b001p-3", 0.125}, 84 {"0b.001p3", 1}, 85 {"0b0.01p2", 1}, 86 87 // hexadecimal mantissa and exponent 88 {"0x0", 0}, 89 {"-0x0", -0}, 90 {"0x0p+10", 0}, 91 {"-0x0p-10", -0}, 92 {"0xff", 255}, 93 {"0X.8p1", 1}, 94 {"-0X0.00008p16", -0.5}, 95 {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64}, 96 {"0x1.fffffffffffffp1023", math.MaxFloat64}, 97 } { 98 var x Float 99 x.SetPrec(53) 100 _, ok := x.SetString(test.s) 101 if !ok { 102 t.Errorf("%s: parse error", test.s) 103 continue 104 } 105 f, _ := x.Float64() 106 want := new(Float).SetFloat64(test.x) 107 if x.Cmp(want) != 0 { 108 t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x) 109 } 110 } 111 } 112 113 const ( 114 below1e23 = 99999999999999974834176 115 above1e23 = 100000000000000008388608 116 ) 117 118 func TestFloat64Format(t *testing.T) { 119 for _, test := range []struct { 120 x float64 121 format byte 122 prec int 123 want string 124 }{ 125 {0, 'f', 0, "0"}, 126 {math.Copysign(0, -1), 'f', 0, "-0"}, 127 {1, 'f', 0, "1"}, 128 {-1, 'f', 0, "-1"}, 129 130 {1.459, 'e', 0, "1e+00"}, 131 {2.459, 'e', 1, "2.5e+00"}, 132 {3.459, 'e', 2, "3.46e+00"}, 133 {4.459, 'e', 3, "4.459e+00"}, 134 {5.459, 'e', 4, "5.4590e+00"}, 135 136 {1.459, 'f', 0, "1"}, 137 {2.459, 'f', 1, "2.5"}, 138 {3.459, 'f', 2, "3.46"}, 139 {4.459, 'f', 3, "4.459"}, 140 {5.459, 'f', 4, "5.4590"}, 141 142 {0, 'b', 0, "0"}, 143 {math.Copysign(0, -1), 'b', 0, "-0"}, 144 {1.0, 'b', 0, "4503599627370496p-52"}, 145 {-1.0, 'b', 0, "-4503599627370496p-52"}, 146 {4503599627370496, 'b', 0, "4503599627370496p+0"}, 147 148 {0, 'p', 0, "0"}, 149 {math.Copysign(0, -1), 'p', 0, "-0"}, 150 {1024.0, 'p', 0, "0x.8p11"}, 151 {-1024.0, 'p', 0, "-0x.8p11"}, 152 153 // all test cases below from strconv/ftoa_test.go 154 {1, 'e', 5, "1.00000e+00"}, 155 {1, 'f', 5, "1.00000"}, 156 {1, 'g', 5, "1"}, 157 // {1, 'g', -1, "1"}, 158 // {20, 'g', -1, "20"}, 159 // {1234567.8, 'g', -1, "1.2345678e+06"}, 160 // {200000, 'g', -1, "200000"}, 161 // {2000000, 'g', -1, "2e+06"}, 162 163 // g conversion and zero suppression 164 {400, 'g', 2, "4e+02"}, 165 {40, 'g', 2, "40"}, 166 {4, 'g', 2, "4"}, 167 {.4, 'g', 2, "0.4"}, 168 {.04, 'g', 2, "0.04"}, 169 {.004, 'g', 2, "0.004"}, 170 {.0004, 'g', 2, "0.0004"}, 171 {.00004, 'g', 2, "4e-05"}, 172 {.000004, 'g', 2, "4e-06"}, 173 174 {0, 'e', 5, "0.00000e+00"}, 175 {0, 'f', 5, "0.00000"}, 176 {0, 'g', 5, "0"}, 177 // {0, 'g', -1, "0"}, 178 179 {-1, 'e', 5, "-1.00000e+00"}, 180 {-1, 'f', 5, "-1.00000"}, 181 {-1, 'g', 5, "-1"}, 182 // {-1, 'g', -1, "-1"}, 183 184 {12, 'e', 5, "1.20000e+01"}, 185 {12, 'f', 5, "12.00000"}, 186 {12, 'g', 5, "12"}, 187 // {12, 'g', -1, "12"}, 188 189 {123456700, 'e', 5, "1.23457e+08"}, 190 {123456700, 'f', 5, "123456700.00000"}, 191 {123456700, 'g', 5, "1.2346e+08"}, 192 // {123456700, 'g', -1, "1.234567e+08"}, 193 194 {1.2345e6, 'e', 5, "1.23450e+06"}, 195 {1.2345e6, 'f', 5, "1234500.00000"}, 196 {1.2345e6, 'g', 5, "1.2345e+06"}, 197 198 {1e23, 'e', 17, "9.99999999999999916e+22"}, 199 {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, 200 {1e23, 'g', 17, "9.9999999999999992e+22"}, 201 202 // {1e23, 'e', -1, "1e+23"}, 203 // {1e23, 'f', -1, "100000000000000000000000"}, 204 // {1e23, 'g', -1, "1e+23"}, 205 206 {below1e23, 'e', 17, "9.99999999999999748e+22"}, 207 {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"}, 208 {below1e23, 'g', 17, "9.9999999999999975e+22"}, 209 210 // {below1e23, 'e', -1, "9.999999999999997e+22"}, 211 // {below1e23, 'f', -1, "99999999999999970000000"}, 212 // {below1e23, 'g', -1, "9.999999999999997e+22"}, 213 214 {above1e23, 'e', 17, "1.00000000000000008e+23"}, 215 {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"}, 216 // {above1e23, 'g', 17, "1.0000000000000001e+23"}, 217 218 // {above1e23, 'e', -1, "1.0000000000000001e+23"}, 219 // {above1e23, 'f', -1, "100000000000000010000000"}, 220 // {above1e23, 'g', -1, "1.0000000000000001e+23"}, 221 222 // {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, 223 // {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, 224 225 // {32, 'g', -1, "32"}, 226 // {32, 'g', 0, "3e+01"}, 227 228 // {100, 'x', -1, "%x"}, 229 230 // {math.NaN(), 'g', -1, "NaN"}, 231 // {-math.NaN(), 'g', -1, "NaN"}, 232 {math.Inf(0), 'g', -1, "+Inf"}, 233 {math.Inf(-1), 'g', -1, "-Inf"}, 234 {-math.Inf(0), 'g', -1, "-Inf"}, 235 236 {-1, 'b', -1, "-4503599627370496p-52"}, 237 238 // fixed bugs 239 {0.9, 'f', 1, "0.9"}, 240 {0.09, 'f', 1, "0.1"}, 241 {0.0999, 'f', 1, "0.1"}, 242 {0.05, 'f', 1, "0.1"}, 243 {0.05, 'f', 0, "0"}, 244 {0.5, 'f', 1, "0.5"}, 245 {0.5, 'f', 0, "0"}, 246 {1.5, 'f', 0, "2"}, 247 248 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 249 // {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, 250 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 251 // {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, 252 253 // Issue 2625. 254 {383260575764816448, 'f', 0, "383260575764816448"}, 255 // {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, 256 } { 257 f := new(Float).SetFloat64(test.x) 258 got := f.Format(test.format, test.prec) 259 if got != test.want { 260 t.Errorf("%v: got %s; want %s", test, got, test.want) 261 } 262 263 if test.format == 'b' && test.x == 0 { 264 continue // 'b' format in strconv.Float requires knowledge of bias for 0.0 265 } 266 if test.format == 'p' { 267 continue // 'p' format not supported in strconv.Format 268 } 269 270 // verify that Float format matches strconv format 271 want := strconv.FormatFloat(test.x, test.format, test.prec, 64) 272 if got != want { 273 t.Errorf("%v: got %s; want %s (strconv)", test, got, want) 274 } 275 } 276 } 277 278 func TestFloatFormat(t *testing.T) { 279 for _, test := range []struct { 280 x string 281 prec uint 282 format byte 283 digits int 284 want string 285 }{ 286 {"0", 10, 'f', 0, "0"}, 287 {"-0", 10, 'f', 0, "-0"}, 288 {"1", 10, 'f', 0, "1"}, 289 {"-1", 10, 'f', 0, "-1"}, 290 291 {"1.459", 100, 'e', 0, "1e+00"}, 292 {"2.459", 100, 'e', 1, "2.5e+00"}, 293 {"3.459", 100, 'e', 2, "3.46e+00"}, 294 {"4.459", 100, 'e', 3, "4.459e+00"}, 295 {"5.459", 100, 'e', 4, "5.4590e+00"}, 296 297 {"1.459", 100, 'E', 0, "1E+00"}, 298 {"2.459", 100, 'E', 1, "2.5E+00"}, 299 {"3.459", 100, 'E', 2, "3.46E+00"}, 300 {"4.459", 100, 'E', 3, "4.459E+00"}, 301 {"5.459", 100, 'E', 4, "5.4590E+00"}, 302 303 {"1.459", 100, 'f', 0, "1"}, 304 {"2.459", 100, 'f', 1, "2.5"}, 305 {"3.459", 100, 'f', 2, "3.46"}, 306 {"4.459", 100, 'f', 3, "4.459"}, 307 {"5.459", 100, 'f', 4, "5.4590"}, 308 309 {"1.459", 100, 'g', 0, "1"}, 310 {"2.459", 100, 'g', 1, "2"}, 311 {"3.459", 100, 'g', 2, "3.5"}, 312 {"4.459", 100, 'g', 3, "4.46"}, 313 {"5.459", 100, 'g', 4, "5.459"}, 314 315 {"1459", 53, 'g', 0, "1e+03"}, 316 {"2459", 53, 'g', 1, "2e+03"}, 317 {"3459", 53, 'g', 2, "3.5e+03"}, 318 {"4459", 53, 'g', 3, "4.46e+03"}, 319 {"5459", 53, 'g', 4, "5459"}, 320 321 {"1459", 53, 'G', 0, "1E+03"}, 322 {"2459", 53, 'G', 1, "2E+03"}, 323 {"3459", 53, 'G', 2, "3.5E+03"}, 324 {"4459", 53, 'G', 3, "4.46E+03"}, 325 {"5459", 53, 'G', 4, "5459"}, 326 327 {"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"}, 328 {"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"}, 329 {"3", 10, 'g', 40, "3"}, 330 331 {"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"}, 332 {"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"}, 333 {"3e40", 100, 'g', 40, "3e+40"}, 334 335 // make sure "stupid" exponents don't stall the machine 336 {"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap3321929"}, 337 {"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p1538481529"}, 338 {"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"}, 339 {"1e-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"}, 340 341 // TODO(gri) need tests for actual large Floats 342 343 {"0", 53, 'b', 0, "0"}, 344 {"-0", 53, 'b', 0, "-0"}, 345 {"1.0", 53, 'b', 0, "4503599627370496p-52"}, 346 {"-1.0", 53, 'b', 0, "-4503599627370496p-52"}, 347 {"4503599627370496", 53, 'b', 0, "4503599627370496p+0"}, 348 349 // issue 9939 350 {"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 351 {"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 352 {"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 353 {"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 354 {"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 355 {"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 356 357 {"3", 350, 'p', 0, "0x.cp2"}, 358 {"03", 350, 'p', 0, "0x.cp2"}, 359 {"3.", 350, 'p', 0, "0x.cp2"}, 360 {"3.0", 350, 'p', 0, "0x.cp2"}, 361 {"3.00", 350, 'p', 0, "0x.cp2"}, 362 {"3.000", 350, 'p', 0, "0x.cp2"}, 363 364 {"0", 64, 'p', 0, "0"}, 365 {"-0", 64, 'p', 0, "-0"}, 366 {"1024.0", 64, 'p', 0, "0x.8p11"}, 367 {"-1024.0", 64, 'p', 0, "-0x.8p11"}, 368 369 // unsupported format 370 {"3.14", 64, 'x', 0, "%x"}, 371 } { 372 f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven) 373 if err != nil { 374 t.Errorf("%v: %s", test, err) 375 continue 376 } 377 378 got := f.Format(test.format, test.digits) 379 if got != test.want { 380 t.Errorf("%v: got %s; want %s", test, got, test.want) 381 } 382 383 // compare with strconv.FormatFloat output if possible 384 // ('p' format is not supported by strconv.FormatFloat, 385 // and its output for 0.0 prints a biased exponent value 386 // as in 0p-1074 which makes no sense to emulate here) 387 if test.prec == 53 && test.format != 'p' && f.Sign() != 0 { 388 f64, acc := f.Float64() 389 if acc != Exact { 390 t.Errorf("%v: expected exact conversion to float64", test) 391 continue 392 } 393 got := strconv.FormatFloat(f64, test.format, test.digits, 64) 394 if got != test.want { 395 t.Errorf("%v: got %s; want %s", test, got, test.want) 396 } 397 } 398 } 399 }