github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/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 "math" 9 "strconv" 10 "testing" 11 ) 12 13 func TestFloatSetFloat64String(t *testing.T) { 14 for _, test := range []struct { 15 s string 16 x float64 17 }{ 18 // basics 19 {"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 32 // various zeros 33 {"0e100", 0}, 34 {"-0e+100", 0}, 35 {"+0e-100", 0}, 36 {"0E100", 0}, 37 {"-0E+100", 0}, 38 {"+0E-100", 0}, 39 40 // various decimal exponent formats 41 {"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}, 47 48 // misc decimal values 49 {"3.14159265", 3.14159265}, 50 {"-687436.79457e-245", -687436.79457e-245}, 51 {"-687436.79457E245", -687436.79457e245}, 52 {".0000000000000000000000000000000000000001", 1e-40}, 53 {"+10000000000000000000000000000000000000000e-0", 1e40}, 54 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}, 95 } { 96 var x Float 97 x.SetPrec(53) 98 _, 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 111 const ( 112 below1e23 = 99999999999999974834176 113 above1e23 = 100000000000000008388608 114 ) 115 116 func TestFloat64Format(t *testing.T) { 117 for _, test := range []struct { 118 x float64 119 format byte 120 prec int 121 want string 122 }{ 123 {0, 'f', 0, "0"}, 124 {math.Copysign(0, -1), 'f', 0, "-0"}, 125 {1, 'f', 0, "1"}, 126 {-1, 'f', 0, "-1"}, 127 128 {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"}, 206 {below1e23, 'g', 17, "9.9999999999999975e+22"}, 207 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"}, 230 {math.Inf(0), 'g', -1, "+Inf"}, 231 {math.Inf(-1), 'g', -1, "-Inf"}, 232 {-math.Inf(0), 'g', -1, "-Inf"}, 233 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"}, 254 } { 255 f := new(Float).SetFloat64(test.x) 256 got := f.Format(test.format, test.prec) 257 if got != test.want { 258 t.Errorf("%v: got %s; want %s", test, got, test.want) 259 } 260 261 if test.format == 'b' && test.x == 0 { 262 continue // 'b' format in strconv.Float requires knowledge of bias for 0.0 263 } 264 if test.format == 'p' { 265 continue // 'p' format not supported in strconv.Format 266 } 267 268 // verify that Float format matches strconv format 269 want := strconv.FormatFloat(test.x, test.format, test.prec, 64) 270 if got != want { 271 t.Errorf("%v: got %s; want %s (strconv)", test, got, want) 272 } 273 } 274 } 275 276 func TestFloatFormat(t *testing.T) { 277 for _, test := range []struct { 278 x string 279 prec uint 280 format byte 281 digits int 282 want string 283 }{ 284 {"0", 10, 'f', 0, "0"}, 285 {"-0", 10, 'f', 0, "-0"}, 286 {"1", 10, 'f', 0, "1"}, 287 {"-1", 10, 'f', 0, "-1"}, 288 289 {"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"}, 294 295 {"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"}, 300 301 {"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"}, 306 307 {"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"}, 312 313 {"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"}, 318 319 {"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"}, 324 325 {"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"}, 326 {"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"}, 327 {"3", 10, 'g', 40, "3"}, 328 329 {"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"}, 330 {"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"}, 331 {"3e40", 100, 'g', 40, "3e+40"}, 332 333 // make sure "stupid" exponents don't stall the machine 334 {"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap3321929"}, 335 {"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p1538481529"}, 336 {"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"}, 337 {"1e-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"}, 338 339 // TODO(gri) need tests for actual large Floats 340 341 {"0", 53, 'b', 0, "0"}, 342 {"-0", 53, 'b', 0, "-0"}, 343 {"1.0", 53, 'b', 0, "4503599627370496p-52"}, 344 {"-1.0", 53, 'b', 0, "-4503599627370496p-52"}, 345 {"4503599627370496", 53, 'b', 0, "4503599627370496p+0"}, 346 347 // issue 9939 348 {"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 349 {"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 350 {"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 351 {"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 352 {"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 353 {"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, 354 355 {"3", 350, 'p', 0, "0x.cp2"}, 356 {"03", 350, 'p', 0, "0x.cp2"}, 357 {"3.", 350, 'p', 0, "0x.cp2"}, 358 {"3.0", 350, 'p', 0, "0x.cp2"}, 359 {"3.00", 350, 'p', 0, "0x.cp2"}, 360 {"3.000", 350, 'p', 0, "0x.cp2"}, 361 362 {"0", 64, 'p', 0, "0"}, 363 {"-0", 64, 'p', 0, "-0"}, 364 {"1024.0", 64, 'p', 0, "0x.8p11"}, 365 {"-1024.0", 64, 'p', 0, "-0x.8p11"}, 366 367 // unsupported format 368 {"3.14", 64, 'x', 0, "%x"}, 369 } { 370 f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven) 371 if err != nil { 372 t.Errorf("%v: %s", test, err) 373 continue 374 } 375 376 got := f.Format(test.format, test.digits) 377 if got != test.want { 378 t.Errorf("%v: got %s; want %s", test, got, test.want) 379 } 380 381 // compare with strconv.FormatFloat output if possible 382 // ('p' format is not supported by strconv.FormatFloat, 383 // and its output for 0.0 prints a biased exponent value 384 // as in 0p-1074 which makes no sense to emulate here) 385 if test.prec == 53 && test.format != 'p' && f.Sign() != 0 { 386 f64, acc := f.Float64() 387 if acc != Exact { 388 t.Errorf("%v: expected exact conversion to float64", test) 389 continue 390 } 391 got := strconv.FormatFloat(f64, test.format, test.digits, 64) 392 if got != test.want { 393 t.Errorf("%v: got %s; want %s", test, got, test.want) 394 } 395 } 396 } 397 }