github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/math/big/rat_test.go (about) 1 // Copyright 2010 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 "encoding/gob" 10 "fmt" 11 "math" 12 "strconv" 13 "strings" 14 "testing" 15 ) 16 17 func TestZeroRat(t *testing.T) { 18 var x, y, z Rat 19 y.SetFrac64(0, 42) 20 21 if x.Cmp(&y) != 0 { 22 t.Errorf("x and y should be both equal and zero") 23 } 24 25 if s := x.String(); s != "0/1" { 26 t.Errorf("got x = %s, want 0/1", s) 27 } 28 29 if s := x.RatString(); s != "0" { 30 t.Errorf("got x = %s, want 0", s) 31 } 32 33 z.Add(&x, &y) 34 if s := z.RatString(); s != "0" { 35 t.Errorf("got x+y = %s, want 0", s) 36 } 37 38 z.Sub(&x, &y) 39 if s := z.RatString(); s != "0" { 40 t.Errorf("got x-y = %s, want 0", s) 41 } 42 43 z.Mul(&x, &y) 44 if s := z.RatString(); s != "0" { 45 t.Errorf("got x*y = %s, want 0", s) 46 } 47 48 // check for division by zero 49 defer func() { 50 if s := recover(); s == nil || s.(string) != "division by zero" { 51 panic(s) 52 } 53 }() 54 z.Quo(&x, &y) 55 } 56 57 var setStringTests = []struct { 58 in, out string 59 ok bool 60 }{ 61 {"0", "0", true}, 62 {"-0", "0", true}, 63 {"1", "1", true}, 64 {"-1", "-1", true}, 65 {"1.", "1", true}, 66 {"1e0", "1", true}, 67 {"1.e1", "10", true}, 68 {in: "1e", ok: false}, 69 {in: "1.e", ok: false}, 70 {in: "1e+14e-5", ok: false}, 71 {in: "1e4.5", ok: false}, 72 {in: "r", ok: false}, 73 {in: "a/b", ok: false}, 74 {in: "a.b", ok: false}, 75 {"-0.1", "-1/10", true}, 76 {"-.1", "-1/10", true}, 77 {"2/4", "1/2", true}, 78 {".25", "1/4", true}, 79 {"-1/5", "-1/5", true}, 80 {"8129567.7690E14", "812956776900000000000", true}, 81 {"78189e+4", "781890000", true}, 82 {"553019.8935e+8", "55301989350000", true}, 83 {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true}, 84 {"9877861857500000E-7", "3951144743/4", true}, 85 {"2169378.417e-3", "2169378417/1000000", true}, 86 {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true}, 87 {"53/70893980658822810696", "53/70893980658822810696", true}, 88 {"106/141787961317645621392", "53/70893980658822810696", true}, 89 {"204211327800791583.81095", "4084226556015831676219/20000", true}, 90 } 91 92 func TestRatSetString(t *testing.T) { 93 for i, test := range setStringTests { 94 x, ok := new(Rat).SetString(test.in) 95 96 if ok { 97 if !test.ok { 98 t.Errorf("#%d SetString(%q) expected failure", i, test.in) 99 } else if x.RatString() != test.out { 100 t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out) 101 } 102 } else if x != nil { 103 t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x) 104 } 105 } 106 } 107 108 func TestRatScan(t *testing.T) { 109 var buf bytes.Buffer 110 for i, test := range setStringTests { 111 x := new(Rat) 112 buf.Reset() 113 buf.WriteString(test.in) 114 115 _, err := fmt.Fscanf(&buf, "%v", x) 116 if err == nil != test.ok { 117 if test.ok { 118 t.Errorf("#%d error: %s", i, err) 119 } else { 120 t.Errorf("#%d expected error", i) 121 } 122 continue 123 } 124 if err == nil && x.RatString() != test.out { 125 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) 126 } 127 } 128 } 129 130 var floatStringTests = []struct { 131 in string 132 prec int 133 out string 134 }{ 135 {"0", 0, "0"}, 136 {"0", 4, "0.0000"}, 137 {"1", 0, "1"}, 138 {"1", 2, "1.00"}, 139 {"-1", 0, "-1"}, 140 {".25", 2, "0.25"}, 141 {".25", 1, "0.3"}, 142 {".25", 3, "0.250"}, 143 {"-1/3", 3, "-0.333"}, 144 {"-2/3", 4, "-0.6667"}, 145 {"0.96", 1, "1.0"}, 146 {"0.999", 2, "1.00"}, 147 {"0.9", 0, "1"}, 148 {".25", -1, "0"}, 149 {".55", -1, "1"}, 150 } 151 152 func TestFloatString(t *testing.T) { 153 for i, test := range floatStringTests { 154 x, _ := new(Rat).SetString(test.in) 155 156 if x.FloatString(test.prec) != test.out { 157 t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out) 158 } 159 } 160 } 161 162 func TestRatSign(t *testing.T) { 163 zero := NewRat(0, 1) 164 for _, a := range setStringTests { 165 x, ok := new(Rat).SetString(a.in) 166 if !ok { 167 continue 168 } 169 s := x.Sign() 170 e := x.Cmp(zero) 171 if s != e { 172 t.Errorf("got %d; want %d for z = %v", s, e, &x) 173 } 174 } 175 } 176 177 var ratCmpTests = []struct { 178 rat1, rat2 string 179 out int 180 }{ 181 {"0", "0/1", 0}, 182 {"1/1", "1", 0}, 183 {"-1", "-2/2", 0}, 184 {"1", "0", 1}, 185 {"0/1", "1/1", -1}, 186 {"-5/1434770811533343057144", "-5/1434770811533343057145", -1}, 187 {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1}, 188 {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1}, 189 {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0}, 190 } 191 192 func TestRatCmp(t *testing.T) { 193 for i, test := range ratCmpTests { 194 x, _ := new(Rat).SetString(test.rat1) 195 y, _ := new(Rat).SetString(test.rat2) 196 197 out := x.Cmp(y) 198 if out != test.out { 199 t.Errorf("#%d got out = %v; want %v", i, out, test.out) 200 } 201 } 202 } 203 204 func TestIsInt(t *testing.T) { 205 one := NewInt(1) 206 for _, a := range setStringTests { 207 x, ok := new(Rat).SetString(a.in) 208 if !ok { 209 continue 210 } 211 i := x.IsInt() 212 e := x.Denom().Cmp(one) == 0 213 if i != e { 214 t.Errorf("got IsInt(%v) == %v; want %v", x, i, e) 215 } 216 } 217 } 218 219 func TestRatAbs(t *testing.T) { 220 zero := new(Rat) 221 for _, a := range setStringTests { 222 x, ok := new(Rat).SetString(a.in) 223 if !ok { 224 continue 225 } 226 e := new(Rat).Set(x) 227 if e.Cmp(zero) < 0 { 228 e.Sub(zero, e) 229 } 230 z := new(Rat).Abs(x) 231 if z.Cmp(e) != 0 { 232 t.Errorf("got Abs(%v) = %v; want %v", x, z, e) 233 } 234 } 235 } 236 237 func TestRatNeg(t *testing.T) { 238 zero := new(Rat) 239 for _, a := range setStringTests { 240 x, ok := new(Rat).SetString(a.in) 241 if !ok { 242 continue 243 } 244 e := new(Rat).Sub(zero, x) 245 z := new(Rat).Neg(x) 246 if z.Cmp(e) != 0 { 247 t.Errorf("got Neg(%v) = %v; want %v", x, z, e) 248 } 249 } 250 } 251 252 func TestRatInv(t *testing.T) { 253 zero := new(Rat) 254 for _, a := range setStringTests { 255 x, ok := new(Rat).SetString(a.in) 256 if !ok { 257 continue 258 } 259 if x.Cmp(zero) == 0 { 260 continue // avoid division by zero 261 } 262 e := new(Rat).SetFrac(x.Denom(), x.Num()) 263 z := new(Rat).Inv(x) 264 if z.Cmp(e) != 0 { 265 t.Errorf("got Inv(%v) = %v; want %v", x, z, e) 266 } 267 } 268 } 269 270 type ratBinFun func(z, x, y *Rat) *Rat 271 type ratBinArg struct { 272 x, y, z string 273 } 274 275 func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) { 276 x, _ := new(Rat).SetString(a.x) 277 y, _ := new(Rat).SetString(a.y) 278 z, _ := new(Rat).SetString(a.z) 279 out := f(new(Rat), x, y) 280 281 if out.Cmp(z) != 0 { 282 t.Errorf("%s #%d got %s want %s", name, i, out, z) 283 } 284 } 285 286 var ratBinTests = []struct { 287 x, y string 288 sum, prod string 289 }{ 290 {"0", "0", "0", "0"}, 291 {"0", "1", "1", "0"}, 292 {"-1", "0", "-1", "0"}, 293 {"-1", "1", "0", "-1"}, 294 {"1", "1", "2", "1"}, 295 {"1/2", "1/2", "1", "1/4"}, 296 {"1/4", "1/3", "7/12", "1/12"}, 297 {"2/5", "-14/3", "-64/15", "-28/15"}, 298 {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"}, 299 {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"}, 300 {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"}, 301 {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"}, 302 {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"}, 303 {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"}, 304 {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"}, 305 {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"}, 306 {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"}, 307 {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"}, 308 } 309 310 func TestRatBin(t *testing.T) { 311 for i, test := range ratBinTests { 312 arg := ratBinArg{test.x, test.y, test.sum} 313 testRatBin(t, i, "Add", (*Rat).Add, arg) 314 315 arg = ratBinArg{test.y, test.x, test.sum} 316 testRatBin(t, i, "Add symmetric", (*Rat).Add, arg) 317 318 arg = ratBinArg{test.sum, test.x, test.y} 319 testRatBin(t, i, "Sub", (*Rat).Sub, arg) 320 321 arg = ratBinArg{test.sum, test.y, test.x} 322 testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg) 323 324 arg = ratBinArg{test.x, test.y, test.prod} 325 testRatBin(t, i, "Mul", (*Rat).Mul, arg) 326 327 arg = ratBinArg{test.y, test.x, test.prod} 328 testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg) 329 330 if test.x != "0" { 331 arg = ratBinArg{test.prod, test.x, test.y} 332 testRatBin(t, i, "Quo", (*Rat).Quo, arg) 333 } 334 335 if test.y != "0" { 336 arg = ratBinArg{test.prod, test.y, test.x} 337 testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg) 338 } 339 } 340 } 341 342 func TestIssue820(t *testing.T) { 343 x := NewRat(3, 1) 344 y := NewRat(2, 1) 345 z := y.Quo(x, y) 346 q := NewRat(3, 2) 347 if z.Cmp(q) != 0 { 348 t.Errorf("got %s want %s", z, q) 349 } 350 351 y = NewRat(3, 1) 352 x = NewRat(2, 1) 353 z = y.Quo(x, y) 354 q = NewRat(2, 3) 355 if z.Cmp(q) != 0 { 356 t.Errorf("got %s want %s", z, q) 357 } 358 359 x = NewRat(3, 1) 360 z = x.Quo(x, x) 361 q = NewRat(3, 3) 362 if z.Cmp(q) != 0 { 363 t.Errorf("got %s want %s", z, q) 364 } 365 } 366 367 var setFrac64Tests = []struct { 368 a, b int64 369 out string 370 }{ 371 {0, 1, "0"}, 372 {0, -1, "0"}, 373 {1, 1, "1"}, 374 {-1, 1, "-1"}, 375 {1, -1, "-1"}, 376 {-1, -1, "1"}, 377 {-9223372036854775808, -9223372036854775808, "1"}, 378 } 379 380 func TestRatSetFrac64Rat(t *testing.T) { 381 for i, test := range setFrac64Tests { 382 x := new(Rat).SetFrac64(test.a, test.b) 383 if x.RatString() != test.out { 384 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) 385 } 386 } 387 } 388 389 func TestRatGobEncoding(t *testing.T) { 390 var medium bytes.Buffer 391 enc := gob.NewEncoder(&medium) 392 dec := gob.NewDecoder(&medium) 393 for _, test := range encodingTests { 394 medium.Reset() // empty buffer for each test case (in case of failures) 395 var tx Rat 396 tx.SetString(test + ".14159265") 397 if err := enc.Encode(&tx); err != nil { 398 t.Errorf("encoding of %s failed: %s", &tx, err) 399 } 400 var rx Rat 401 if err := dec.Decode(&rx); err != nil { 402 t.Errorf("decoding of %s failed: %s", &tx, err) 403 } 404 if rx.Cmp(&tx) != 0 { 405 t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx) 406 } 407 } 408 } 409 410 func TestIssue2379(t *testing.T) { 411 // 1) no aliasing 412 q := NewRat(3, 2) 413 x := new(Rat) 414 x.SetFrac(NewInt(3), NewInt(2)) 415 if x.Cmp(q) != 0 { 416 t.Errorf("1) got %s want %s", x, q) 417 } 418 419 // 2) aliasing of numerator 420 x = NewRat(2, 3) 421 x.SetFrac(NewInt(3), x.Num()) 422 if x.Cmp(q) != 0 { 423 t.Errorf("2) got %s want %s", x, q) 424 } 425 426 // 3) aliasing of denominator 427 x = NewRat(2, 3) 428 x.SetFrac(x.Denom(), NewInt(2)) 429 if x.Cmp(q) != 0 { 430 t.Errorf("3) got %s want %s", x, q) 431 } 432 433 // 4) aliasing of numerator and denominator 434 x = NewRat(2, 3) 435 x.SetFrac(x.Denom(), x.Num()) 436 if x.Cmp(q) != 0 { 437 t.Errorf("4) got %s want %s", x, q) 438 } 439 440 // 5) numerator and denominator are the same 441 q = NewRat(1, 1) 442 x = new(Rat) 443 n := NewInt(7) 444 x.SetFrac(n, n) 445 if x.Cmp(q) != 0 { 446 t.Errorf("5) got %s want %s", x, q) 447 } 448 } 449 450 func TestIssue3521(t *testing.T) { 451 a := new(Int) 452 b := new(Int) 453 a.SetString("64375784358435883458348587", 0) 454 b.SetString("4789759874531", 0) 455 456 // 0) a raw zero value has 1 as denominator 457 zero := new(Rat) 458 one := NewInt(1) 459 if zero.Denom().Cmp(one) != 0 { 460 t.Errorf("0) got %s want %s", zero.Denom(), one) 461 } 462 463 // 1a) a zero value remains zero independent of denominator 464 x := new(Rat) 465 x.Denom().Set(new(Int).Neg(b)) 466 if x.Cmp(zero) != 0 { 467 t.Errorf("1a) got %s want %s", x, zero) 468 } 469 470 // 1b) a zero value may have a denominator != 0 and != 1 471 x.Num().Set(a) 472 qab := new(Rat).SetFrac(a, b) 473 if x.Cmp(qab) != 0 { 474 t.Errorf("1b) got %s want %s", x, qab) 475 } 476 477 // 2a) an integral value becomes a fraction depending on denominator 478 x.SetFrac64(10, 2) 479 x.Denom().SetInt64(3) 480 q53 := NewRat(5, 3) 481 if x.Cmp(q53) != 0 { 482 t.Errorf("2a) got %s want %s", x, q53) 483 } 484 485 // 2b) an integral value becomes a fraction depending on denominator 486 x = NewRat(10, 2) 487 x.Denom().SetInt64(3) 488 if x.Cmp(q53) != 0 { 489 t.Errorf("2b) got %s want %s", x, q53) 490 } 491 492 // 3) changing the numerator/denominator of a Rat changes the Rat 493 x.SetFrac(a, b) 494 a = x.Num() 495 b = x.Denom() 496 a.SetInt64(5) 497 b.SetInt64(3) 498 if x.Cmp(q53) != 0 { 499 t.Errorf("3) got %s want %s", x, q53) 500 } 501 } 502 503 // Test inputs to Rat.SetString. The prefix "long:" causes the test 504 // to be skipped in --test.short mode. (The threshold is about 500us.) 505 var float64inputs = []string{ 506 // Constants plundered from strconv/testfp.txt. 507 508 // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP 509 "5e+125", 510 "69e+267", 511 "999e-026", 512 "7861e-034", 513 "75569e-254", 514 "928609e-261", 515 "9210917e+080", 516 "84863171e+114", 517 "653777767e+273", 518 "5232604057e-298", 519 "27235667517e-109", 520 "653532977297e-123", 521 "3142213164987e-294", 522 "46202199371337e-072", 523 "231010996856685e-073", 524 "9324754620109615e+212", 525 "78459735791271921e+049", 526 "272104041512242479e+200", 527 "6802601037806061975e+198", 528 "20505426358836677347e-221", 529 "836168422905420598437e-234", 530 "4891559871276714924261e+222", 531 532 // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP 533 "9e-265", 534 "85e-037", 535 "623e+100", 536 "3571e+263", 537 "81661e+153", 538 "920657e-023", 539 "4603285e-024", 540 "87575437e-309", 541 "245540327e+122", 542 "6138508175e+120", 543 "83356057653e+193", 544 "619534293513e+124", 545 "2335141086879e+218", 546 "36167929443327e-159", 547 "609610927149051e-255", 548 "3743626360493413e-165", 549 "94080055902682397e-242", 550 "899810892172646163e+283", 551 "7120190517612959703e+120", 552 "25188282901709339043e-252", 553 "308984926168550152811e-052", 554 "6372891218502368041059e+064", 555 556 // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP 557 "5e-20", 558 "67e+14", 559 "985e+15", 560 "7693e-42", 561 "55895e-16", 562 "996622e-44", 563 "7038531e-32", 564 "60419369e-46", 565 "702990899e-20", 566 "6930161142e-48", 567 "25933168707e+13", 568 "596428896559e+20", 569 570 // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP 571 "3e-23", 572 "57e+18", 573 "789e-35", 574 "2539e-18", 575 "76173e+28", 576 "887745e-11", 577 "5382571e-37", 578 "82381273e-35", 579 "750486563e-38", 580 "3752432815e-39", 581 "75224575729e-45", 582 "459926601011e+15", 583 584 // Constants plundered from strconv/atof_test.go. 585 586 "0", 587 "1", 588 "+1", 589 "1e23", 590 "1E23", 591 "100000000000000000000000", 592 "1e-100", 593 "123456700", 594 "99999999999999974834176", 595 "100000000000000000000001", 596 "100000000000000008388608", 597 "100000000000000016777215", 598 "100000000000000016777216", 599 "-1", 600 "-0.1", 601 "-0", // NB: exception made for this input 602 "1e-20", 603 "625e-3", 604 605 // largest float64 606 "1.7976931348623157e308", 607 "-1.7976931348623157e308", 608 // next float64 - too large 609 "1.7976931348623159e308", 610 "-1.7976931348623159e308", 611 // the border is ...158079 612 // borderline - okay 613 "1.7976931348623158e308", 614 "-1.7976931348623158e308", 615 // borderline - too large 616 "1.797693134862315808e308", 617 "-1.797693134862315808e308", 618 619 // a little too large 620 "1e308", 621 "2e308", 622 "1e309", 623 624 // way too large 625 "1e310", 626 "-1e310", 627 "1e400", 628 "-1e400", 629 "long:1e400000", 630 "long:-1e400000", 631 632 // denormalized 633 "1e-305", 634 "1e-306", 635 "1e-307", 636 "1e-308", 637 "1e-309", 638 "1e-310", 639 "1e-322", 640 // smallest denormal 641 "5e-324", 642 "4e-324", 643 "3e-324", 644 // too small 645 "2e-324", 646 // way too small 647 "1e-350", 648 "long:1e-400000", 649 // way too small, negative 650 "-1e-350", 651 "long:-1e-400000", 652 653 // try to overflow exponent 654 // [Disabled: too slow and memory-hungry with rationals.] 655 // "1e-4294967296", 656 // "1e+4294967296", 657 // "1e-18446744073709551616", 658 // "1e+18446744073709551616", 659 660 // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 661 "2.2250738585072012e-308", 662 // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 663 664 "2.2250738585072011e-308", 665 666 // A very large number (initially wrongly parsed by the fast algorithm). 667 "4.630813248087435e+307", 668 669 // A different kind of very large number. 670 "22.222222222222222", 671 "long:2." + strings.Repeat("2", 4000) + "e+1", 672 673 // Exactly halfway between 1 and math.Nextafter(1, 2). 674 // Round to even (down). 675 "1.00000000000000011102230246251565404236316680908203125", 676 // Slightly lower; still round down. 677 "1.00000000000000011102230246251565404236316680908203124", 678 // Slightly higher; round up. 679 "1.00000000000000011102230246251565404236316680908203126", 680 // Slightly higher, but you have to read all the way to the end. 681 "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", 682 683 // Smallest denormal, 2^(-1022-52) 684 "4.940656458412465441765687928682213723651e-324", 685 // Half of smallest denormal, 2^(-1022-53) 686 "2.470328229206232720882843964341106861825e-324", 687 // A little more than the exact half of smallest denormal 688 // 2^-1075 + 2^-1100. (Rounds to 1p-1074.) 689 "2.470328302827751011111470718709768633275e-324", 690 // The exact halfway between smallest normal and largest denormal: 691 // 2^-1022 - 2^-1075. (Rounds to 2^-1022.) 692 "2.225073858507201136057409796709131975935e-308", 693 694 "1152921504606846975", // 1<<60 - 1 695 "-1152921504606846975", // -(1<<60 - 1) 696 "1152921504606846977", // 1<<60 + 1 697 "-1152921504606846977", // -(1<<60 + 1) 698 699 "1/3", 700 } 701 702 func TestFloat64SpecialCases(t *testing.T) { 703 for _, input := range float64inputs { 704 if strings.HasPrefix(input, "long:") { 705 if testing.Short() { 706 continue 707 } 708 input = input[len("long:"):] 709 } 710 711 r, ok := new(Rat).SetString(input) 712 if !ok { 713 t.Errorf("Rat.SetString(%q) failed", input) 714 continue 715 } 716 f, exact := r.Float64() 717 718 // 1. Check string -> Rat -> float64 conversions are 719 // consistent with strconv.ParseFloat. 720 // Skip this check if the input uses "a/b" rational syntax. 721 if !strings.Contains(input, "/") { 722 e, _ := strconv.ParseFloat(input, 64) 723 724 // Careful: negative Rats too small for 725 // float64 become -0, but Rat obviously cannot 726 // preserve the sign from SetString("-0"). 727 switch { 728 case math.Float64bits(e) == math.Float64bits(f): 729 // Ok: bitwise equal. 730 case f == 0 && r.Num().BitLen() == 0: 731 // Ok: Rat(0) is equivalent to both +/- float64(0). 732 default: 733 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e) 734 } 735 } 736 737 if !isFinite(f) { 738 continue 739 } 740 741 // 2. Check f is best approximation to r. 742 if !checkIsBestApprox(t, f, r) { 743 // Append context information. 744 t.Errorf("(input was %q)", input) 745 } 746 747 // 3. Check f->R->f roundtrip is non-lossy. 748 checkNonLossyRoundtrip(t, f) 749 750 // 4. Check exactness using slow algorithm. 751 if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact { 752 t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact) 753 } 754 } 755 } 756 757 func TestFloat64Distribution(t *testing.T) { 758 // Generate a distribution of (sign, mantissa, exp) values 759 // broader than the float64 range, and check Rat.Float64() 760 // always picks the closest float64 approximation. 761 var add = []int64{ 762 0, 763 1, 764 3, 765 5, 766 7, 767 9, 768 11, 769 } 770 var winc, einc = uint64(1), int(1) // soak test (~75s on x86-64) 771 if testing.Short() { 772 winc, einc = 10, 500 // quick test (~12ms on x86-64) 773 } 774 775 for _, sign := range "+-" { 776 for _, a := range add { 777 for wid := uint64(0); wid < 60; wid += winc { 778 b := int64(1<<wid + a) 779 if sign == '-' { 780 b = -b 781 } 782 for exp := -1100; exp < 1100; exp += einc { 783 num, den := NewInt(b), NewInt(1) 784 if exp > 0 { 785 num.Lsh(num, uint(exp)) 786 } else { 787 den.Lsh(den, uint(-exp)) 788 } 789 r := new(Rat).SetFrac(num, den) 790 f, _ := r.Float64() 791 792 if !checkIsBestApprox(t, f, r) { 793 // Append context information. 794 t.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)", 795 b, exp, f, f, math.Ldexp(float64(b), exp), r) 796 } 797 798 checkNonLossyRoundtrip(t, f) 799 } 800 } 801 } 802 } 803 } 804 805 // TestFloat64NonFinite checks that SetFloat64 of a non-finite value 806 // returns nil. 807 func TestSetFloat64NonFinite(t *testing.T) { 808 for _, f := range []float64{math.NaN(), math.Inf(+1), math.Inf(-1)} { 809 var r Rat 810 if r2 := r.SetFloat64(f); r2 != nil { 811 t.Errorf("SetFloat64(%g) was %v, want nil", f, r2) 812 } 813 } 814 } 815 816 // checkNonLossyRoundtrip checks that a float->Rat->float roundtrip is 817 // non-lossy for finite f. 818 func checkNonLossyRoundtrip(t *testing.T, f float64) { 819 if !isFinite(f) { 820 return 821 } 822 r := new(Rat).SetFloat64(f) 823 if r == nil { 824 t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f) 825 return 826 } 827 f2, exact := r.Float64() 828 if f != f2 || !exact { 829 t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b", 830 f, f2, f2, exact, f, f, true, f2-f) 831 } 832 } 833 834 // delta returns the absolute difference between r and f. 835 func delta(r *Rat, f float64) *Rat { 836 d := new(Rat).Sub(r, new(Rat).SetFloat64(f)) 837 return d.Abs(d) 838 } 839 840 // checkIsBestApprox checks that f is the best possible float64 841 // approximation of r. 842 // Returns true on success. 843 func checkIsBestApprox(t *testing.T, f float64, r *Rat) bool { 844 if math.Abs(f) >= math.MaxFloat64 { 845 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64). 846 // But we have tests for these special cases. 847 return true 848 } 849 850 // r must be strictly between f0 and f1, the floats bracketing f. 851 f0 := math.Nextafter(f, math.Inf(-1)) 852 f1 := math.Nextafter(f, math.Inf(+1)) 853 854 // For f to be correct, r must be closer to f than to f0 or f1. 855 df := delta(r, f) 856 df0 := delta(r, f0) 857 df1 := delta(r, f1) 858 if df.Cmp(df0) > 0 { 859 t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0) 860 return false 861 } 862 if df.Cmp(df1) > 0 { 863 t.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1) 864 return false 865 } 866 if df.Cmp(df0) == 0 && !isEven(f) { 867 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0) 868 return false 869 } 870 if df.Cmp(df1) == 0 && !isEven(f) { 871 t.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1) 872 return false 873 } 874 return true 875 } 876 877 func isEven(f float64) bool { return math.Float64bits(f)&1 == 0 } 878 879 func TestIsFinite(t *testing.T) { 880 finites := []float64{ 881 1.0 / 3, 882 4891559871276714924261e+222, 883 math.MaxFloat64, 884 math.SmallestNonzeroFloat64, 885 -math.MaxFloat64, 886 -math.SmallestNonzeroFloat64, 887 } 888 for _, f := range finites { 889 if !isFinite(f) { 890 t.Errorf("!IsFinite(%g (%b))", f, f) 891 } 892 } 893 nonfinites := []float64{ 894 math.NaN(), 895 math.Inf(-1), 896 math.Inf(+1), 897 } 898 for _, f := range nonfinites { 899 if isFinite(f) { 900 t.Errorf("IsFinite(%g, (%b))", f, f) 901 } 902 } 903 }