github.com/XiaoMi/Gaea@v1.2.5/parser/tidb-types/mydecimal_test.go (about) 1 // Copyright 2016 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package types 15 16 import ( 17 "strings" 18 "testing" 19 20 . "github.com/pingcap/check" 21 ) 22 23 var _ = Suite(&testMyDecimalSuite{}) 24 25 type testMyDecimalSuite struct { 26 } 27 28 func (s *testMyDecimalSuite) TestFromInt(c *C) { 29 tests := []struct { 30 input int64 31 output string 32 }{ 33 {-12345, "-12345"}, 34 {-1, "-1"}, 35 {1, "1"}, 36 {-9223372036854775807, "-9223372036854775807"}, 37 {-9223372036854775808, "-9223372036854775808"}, 38 } 39 for _, tt := range tests { 40 dec := NewDecFromInt(tt.input) 41 str := dec.ToString() 42 c.Check(string(str), Equals, tt.output) 43 } 44 } 45 46 func (s *testMyDecimalSuite) TestFromUint(c *C) { 47 tests := []struct { 48 input uint64 49 output string 50 }{ 51 {12345, "12345"}, 52 {0, "0"}, 53 {18446744073709551615, "18446744073709551615"}, 54 } 55 for _, tt := range tests { 56 var dec MyDecimal 57 dec.FromUint(tt.input) 58 str := dec.ToString() 59 c.Check(string(str), Equals, tt.output) 60 } 61 } 62 63 func (s *testMyDecimalSuite) TestToInt(c *C) { 64 tests := []struct { 65 input string 66 output int64 67 err error 68 }{ 69 {"18446744073709551615", 9223372036854775807, ErrOverflow}, 70 {"-1", -1, nil}, 71 {"1", 1, nil}, 72 {"-1.23", -1, ErrTruncated}, 73 {"-9223372036854775807", -9223372036854775807, nil}, 74 {"-9223372036854775808", -9223372036854775808, nil}, 75 {"9223372036854775808", 9223372036854775807, ErrOverflow}, 76 {"-9223372036854775809", -9223372036854775808, ErrOverflow}, 77 } 78 for _, tt := range tests { 79 var dec MyDecimal 80 dec.FromString([]byte(tt.input)) 81 result, ec := dec.ToInt() 82 c.Check(ec, Equals, tt.err) 83 c.Check(result, Equals, tt.output) 84 } 85 } 86 87 func (s *testMyDecimalSuite) TestToUint(c *C) { 88 tests := []struct { 89 input string 90 output uint64 91 err error 92 }{ 93 {"12345", 12345, nil}, 94 {"0", 0, nil}, 95 /* ULLONG_MAX = 18446744073709551615ULL */ 96 {"18446744073709551615", 18446744073709551615, nil}, 97 {"18446744073709551616", 18446744073709551615, ErrOverflow}, 98 {"-1", 0, ErrOverflow}, 99 {"1.23", 1, ErrTruncated}, 100 {"9999999999999999999999999.000", 18446744073709551615, ErrOverflow}, 101 } 102 for _, tt := range tests { 103 var dec MyDecimal 104 dec.FromString([]byte(tt.input)) 105 result, ec := dec.ToUint() 106 c.Check(ec, Equals, tt.err) 107 c.Check(result, Equals, tt.output) 108 } 109 } 110 111 func (s *testMyDecimalSuite) TestFromFloat(c *C) { 112 tests := []struct { 113 s string 114 f float64 115 }{ 116 {"12345", 12345}, 117 {"123.45", 123.45}, 118 {"-123.45", -123.45}, 119 {"0.00012345000098765", 0.00012345000098765}, 120 {"1234500009876.5", 1234500009876.5}, 121 } 122 for _, tt := range tests { 123 dec := NewDecFromFloatForTest(tt.f) 124 str := dec.ToString() 125 c.Check(string(str), Equals, tt.s) 126 } 127 } 128 129 func (s *testMyDecimalSuite) TestToFloat(c *C) { 130 tests := []struct { 131 s string 132 f float64 133 }{ 134 {"12345", 12345}, 135 {"123.45", 123.45}, 136 {"-123.45", -123.45}, 137 {"0.00012345000098765", 0.00012345000098765}, 138 {"1234500009876.5", 1234500009876.5}, 139 } 140 for _, ca := range tests { 141 var dec MyDecimal 142 dec.FromString([]byte(ca.s)) 143 f, err := dec.ToFloat64() 144 c.Check(err, IsNil) 145 c.Check(f, Equals, ca.f) 146 } 147 } 148 149 func (s *testMyDecimalSuite) TestToHashKey(c *C) { 150 tests := []struct { 151 numbers []string 152 }{ 153 {[]string{"1.1", "1.1000", "1.1000000", "1.10000000000", "01.1", "0001.1", "001.1000000"}}, 154 {[]string{"-1.1", "-1.1000", "-1.1000000", "-1.10000000000", "-01.1", "-0001.1", "-001.1000000"}}, 155 {[]string{".1", "0.1", "000000.1", ".10000", "0000.10000", "000000000000000000.1"}}, 156 {[]string{"0", "0000", ".0", ".00000", "00000.00000", "-0", "-0000", "-.0", "-.00000", "-00000.00000"}}, 157 {[]string{".123456789123456789", ".1234567891234567890", ".12345678912345678900", ".123456789123456789000", ".1234567891234567890000", "0.123456789123456789", 158 ".1234567891234567890000000000", "0000000.123456789123456789000"}}, 159 {[]string{"12345", "012345", "0012345", "0000012345", "0000000012345", "00000000000012345", "12345.", "12345.00", "12345.000000000", "000012345.0000"}}, 160 {[]string{"123E5", "12300000", "00123E5", "000000123E5", "12300000.00000000"}}, 161 {[]string{"123E-2", "1.23", "00000001.23", "1.2300000000000000", "000000001.23000000000000"}}, 162 } 163 for _, ca := range tests { 164 keys := make([]string, 0, len(ca.numbers)) 165 for _, num := range ca.numbers { 166 var dec MyDecimal 167 c.Check(dec.FromString([]byte(num)), IsNil) 168 key, err := dec.ToHashKey() 169 c.Check(err, IsNil) 170 keys = append(keys, string(key)) 171 } 172 173 for i := 1; i < len(keys); i++ { 174 c.Check(keys[0], Equals, keys[i]) 175 } 176 } 177 178 binTests := []struct { 179 hashNumbers []string 180 binNumbers []string 181 }{ 182 {[]string{"1.1", "1.1000", "1.1000000", "1.10000000000", "01.1", "0001.1", "001.1000000"}, 183 []string{"1.1", "0001.1", "01.1"}}, 184 {[]string{"-1.1", "-1.1000", "-1.1000000", "-1.10000000000", "-01.1", "-0001.1", "-001.1000000"}, 185 []string{"-1.1", "-0001.1", "-01.1"}}, 186 {[]string{".1", "0.1", "000000.1", ".10000", "0000.10000", "000000000000000000.1"}, 187 []string{".1", "0.1", "000000.1", "00.1"}}, 188 {[]string{"0", "0000", ".0", ".00000", "00000.00000", "-0", "-0000", "-.0", "-.00000", "-00000.00000"}, 189 []string{"0", "0000", "00", "-0", "-00", "-000000"}}, 190 {[]string{".123456789123456789", ".1234567891234567890", ".12345678912345678900", ".123456789123456789000", ".1234567891234567890000", "0.123456789123456789", 191 ".1234567891234567890000000000", "0000000.123456789123456789000"}, 192 []string{".123456789123456789", "0.123456789123456789", "0000.123456789123456789", "0000000.123456789123456789"}}, 193 {[]string{"12345", "012345", "0012345", "0000012345", "0000000012345", "00000000000012345", "12345.", "12345.00", "12345.000000000", "000012345.0000"}, 194 []string{"12345", "012345", "000012345", "000000000000012345"}}, 195 {[]string{"123E5", "12300000", "00123E5", "000000123E5", "12300000.00000000"}, 196 []string{"12300000", "123E5", "00123E5", "0000000000123E5"}}, 197 {[]string{"123E-2", "1.23", "00000001.23", "1.2300000000000000", "000000001.23000000000000"}, 198 []string{"123E-2", "1.23", "000001.23", "0000000000001.23"}}, 199 } 200 for _, ca := range binTests { 201 keys := make([]string, 0, len(ca.hashNumbers)+len(ca.binNumbers)) 202 for _, num := range ca.hashNumbers { 203 var dec MyDecimal 204 c.Check(dec.FromString([]byte(num)), IsNil) 205 key, err := dec.ToHashKey() 206 c.Check(err, IsNil) 207 keys = append(keys, string(key)) 208 } 209 for _, num := range ca.binNumbers { 210 var dec MyDecimal 211 c.Check(dec.FromString([]byte(num)), IsNil) 212 prec, frac := dec.PrecisionAndFrac() // remove leading zeros but trailing zeros remain 213 key, err := dec.ToBin(prec, frac) 214 c.Check(err, IsNil) 215 keys = append(keys, string(key)) 216 } 217 218 for i := 1; i < len(keys); i++ { 219 c.Check(keys[0], Equals, keys[i]) 220 } 221 } 222 } 223 224 func (s *testMyDecimalSuite) TestRemoveTrailingZeros(c *C) { 225 tests := []string{ 226 "0", "0.0", ".0", ".00000000", "0.0000", "0000", "0000.0", "0000.000", 227 "-0", "-0.0", "-.0", "-.00000000", "-0.0000", "-0000", "-0000.0", "-0000.000", 228 "123123123", "213123.", "21312.000", "21321.123", "213.1230000", "213123.000123000", 229 "-123123123", "-213123.", "-21312.000", "-21321.123", "-213.1230000", "-213123.000123000", 230 "123E5", "12300E-5", "0.00100E1", "0.001230E-3", 231 "123987654321.123456789000", "000000000123", "123456789.987654321", "999.999000", 232 } 233 for _, ca := range tests { 234 var dec MyDecimal 235 c.Check(dec.FromString([]byte(ca)), IsNil) 236 237 // calculate the number of digits after point but trailing zero 238 digitsFracExp := 0 239 str := string(dec.ToString()) 240 point := strings.Index(str, ".") 241 if point != -1 { 242 pos := len(str) - 1 243 for pos > point { 244 if str[pos] != '0' { 245 break 246 } 247 pos-- 248 } 249 digitsFracExp = pos - point 250 } 251 252 _, digitsFrac := dec.removeTrailingZeros() 253 c.Check(digitsFrac, Equals, digitsFracExp) 254 } 255 } 256 257 func (s *testMyDecimalSuite) TestShift(c *C) { 258 type tcase struct { 259 input string 260 shift int 261 output string 262 err error 263 } 264 var dotest = func(c *C, tests []tcase) { 265 for _, ca := range tests { 266 var dec MyDecimal 267 err := dec.FromString([]byte(ca.input)) 268 c.Check(err, IsNil) 269 origin := dec 270 err = dec.Shift(ca.shift) 271 c.Check(err, Equals, ca.err) 272 result := dec.ToString() 273 c.Check(string(result), Equals, ca.output, Commentf("origin:%s\ndec:%s", origin.String(), string(result))) 274 } 275 } 276 wordBufLen = maxWordBufLen 277 tests := []tcase{ 278 {"123.123", 1, "1231.23", nil}, 279 {"123457189.123123456789000", 1, "1234571891.23123456789", nil}, 280 {"123457189.123123456789000", 8, "12345718912312345.6789", nil}, 281 {"123457189.123123456789000", 9, "123457189123123456.789", nil}, 282 {"123457189.123123456789000", 10, "1234571891231234567.89", nil}, 283 {"123457189.123123456789000", 17, "12345718912312345678900000", nil}, 284 {"123457189.123123456789000", 18, "123457189123123456789000000", nil}, 285 {"123457189.123123456789000", 19, "1234571891231234567890000000", nil}, 286 {"123457189.123123456789000", 26, "12345718912312345678900000000000000", nil}, 287 {"123457189.123123456789000", 27, "123457189123123456789000000000000000", nil}, 288 {"123457189.123123456789000", 28, "1234571891231234567890000000000000000", nil}, 289 {"000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", nil}, 290 {"00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", nil}, 291 {"00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", nil}, 292 {"123", 1, "1230", nil}, 293 {"123", 10, "1230000000000", nil}, 294 {".123", 1, "1.23", nil}, 295 {".123", 10, "1230000000", nil}, 296 {".123", 14, "12300000000000", nil}, 297 {"000.000", 1000, "0", nil}, 298 {"000.", 1000, "0", nil}, 299 {".000", 1000, "0", nil}, 300 {"1", 1000, "1", ErrOverflow}, 301 {"123.123", -1, "12.3123", nil}, 302 {"123987654321.123456789000", -1, "12398765432.1123456789", nil}, 303 {"123987654321.123456789000", -2, "1239876543.21123456789", nil}, 304 {"123987654321.123456789000", -3, "123987654.321123456789", nil}, 305 {"123987654321.123456789000", -8, "1239.87654321123456789", nil}, 306 {"123987654321.123456789000", -9, "123.987654321123456789", nil}, 307 {"123987654321.123456789000", -10, "12.3987654321123456789", nil}, 308 {"123987654321.123456789000", -11, "1.23987654321123456789", nil}, 309 {"123987654321.123456789000", -12, "0.123987654321123456789", nil}, 310 {"123987654321.123456789000", -13, "0.0123987654321123456789", nil}, 311 {"123987654321.123456789000", -14, "0.00123987654321123456789", nil}, 312 {"00000087654321.123456789000", -14, "0.00000087654321123456789", nil}, 313 } 314 dotest(c, tests) 315 wordBufLen = 2 316 tests = []tcase{ 317 {"123.123", -2, "1.23123", nil}, 318 {"123.123", -3, "0.123123", nil}, 319 {"123.123", -6, "0.000123123", nil}, 320 {"123.123", -7, "0.0000123123", nil}, 321 {"123.123", -15, "0.000000000000123123", nil}, 322 {"123.123", -16, "0.000000000000012312", ErrTruncated}, 323 {"123.123", -17, "0.000000000000001231", ErrTruncated}, 324 {"123.123", -18, "0.000000000000000123", ErrTruncated}, 325 {"123.123", -19, "0.000000000000000012", ErrTruncated}, 326 {"123.123", -20, "0.000000000000000001", ErrTruncated}, 327 {"123.123", -21, "0", ErrTruncated}, 328 {".000000000123", -1, "0.0000000000123", nil}, 329 {".000000000123", -6, "0.000000000000000123", nil}, 330 {".000000000123", -7, "0.000000000000000012", ErrTruncated}, 331 {".000000000123", -8, "0.000000000000000001", ErrTruncated}, 332 {".000000000123", -9, "0", ErrTruncated}, 333 {".000000000123", 1, "0.00000000123", nil}, 334 {".000000000123", 8, "0.0123", nil}, 335 {".000000000123", 9, "0.123", nil}, 336 {".000000000123", 10, "1.23", nil}, 337 {".000000000123", 17, "12300000", nil}, 338 {".000000000123", 18, "123000000", nil}, 339 {".000000000123", 19, "1230000000", nil}, 340 {".000000000123", 20, "12300000000", nil}, 341 {".000000000123", 21, "123000000000", nil}, 342 {".000000000123", 22, "1230000000000", nil}, 343 {".000000000123", 23, "12300000000000", nil}, 344 {".000000000123", 24, "123000000000000", nil}, 345 {".000000000123", 25, "1230000000000000", nil}, 346 {".000000000123", 26, "12300000000000000", nil}, 347 {".000000000123", 27, "123000000000000000", nil}, 348 {".000000000123", 28, "0.000000000123", ErrOverflow}, 349 {"123456789.987654321", -1, "12345678.998765432", ErrTruncated}, 350 {"123456789.987654321", -2, "1234567.899876543", ErrTruncated}, 351 {"123456789.987654321", -8, "1.234567900", ErrTruncated}, 352 {"123456789.987654321", -9, "0.123456789987654321", nil}, 353 {"123456789.987654321", -10, "0.012345678998765432", ErrTruncated}, 354 {"123456789.987654321", -17, "0.000000001234567900", ErrTruncated}, 355 {"123456789.987654321", -18, "0.000000000123456790", ErrTruncated}, 356 {"123456789.987654321", -19, "0.000000000012345679", ErrTruncated}, 357 {"123456789.987654321", -26, "0.000000000000000001", ErrTruncated}, 358 {"123456789.987654321", -27, "0", ErrTruncated}, 359 {"123456789.987654321", 1, "1234567900", ErrTruncated}, 360 {"123456789.987654321", 2, "12345678999", ErrTruncated}, 361 {"123456789.987654321", 4, "1234567899877", ErrTruncated}, 362 {"123456789.987654321", 8, "12345678998765432", ErrTruncated}, 363 {"123456789.987654321", 9, "123456789987654321", nil}, 364 {"123456789.987654321", 10, "123456789.987654321", ErrOverflow}, 365 {"123456789.987654321", 0, "123456789.987654321", nil}, 366 } 367 dotest(c, tests) 368 wordBufLen = maxWordBufLen 369 } 370 371 func (s *testMyDecimalSuite) TestRoundWithHalfEven(c *C) { 372 tests := []struct { 373 input string 374 scale int 375 output string 376 err error 377 }{ 378 {"123456789.987654321", 1, "123456790.0", nil}, 379 {"15.1", 0, "15", nil}, 380 {"15.5", 0, "16", nil}, 381 {"15.9", 0, "16", nil}, 382 {"-15.1", 0, "-15", nil}, 383 {"-15.5", 0, "-16", nil}, 384 {"-15.9", 0, "-16", nil}, 385 {"15.1", 1, "15.1", nil}, 386 {"-15.1", 1, "-15.1", nil}, 387 {"15.17", 1, "15.2", nil}, 388 {"15.4", -1, "20", nil}, 389 {"-15.4", -1, "-20", nil}, 390 {"5.4", -1, "10", nil}, 391 {".999", 0, "1", nil}, 392 {"999999999", -9, "1000000000", nil}, 393 } 394 395 for _, ca := range tests { 396 var dec MyDecimal 397 dec.FromString([]byte(ca.input)) 398 var rounded MyDecimal 399 err := dec.Round(&rounded, ca.scale, ModeHalfEven) 400 c.Check(err, Equals, ca.err) 401 result := rounded.ToString() 402 c.Check(string(result), Equals, ca.output) 403 } 404 } 405 406 func (s *testMyDecimalSuite) TestRoundWithTruncate(c *C) { 407 tests := []struct { 408 input string 409 scale int 410 output string 411 err error 412 }{ 413 {"123456789.987654321", 1, "123456789.9", nil}, 414 {"15.1", 0, "15", nil}, 415 {"15.5", 0, "15", nil}, 416 {"15.9", 0, "15", nil}, 417 {"-15.1", 0, "-15", nil}, 418 {"-15.5", 0, "-15", nil}, 419 {"-15.9", 0, "-15", nil}, 420 {"15.1", 1, "15.1", nil}, 421 {"-15.1", 1, "-15.1", nil}, 422 {"15.17", 1, "15.1", nil}, 423 {"15.4", -1, "10", nil}, 424 {"-15.4", -1, "-10", nil}, 425 {"5.4", -1, "0", nil}, 426 {".999", 0, "0", nil}, 427 {"999999999", -9, "0", nil}, 428 } 429 for _, ca := range tests { 430 var dec MyDecimal 431 dec.FromString([]byte(ca.input)) 432 var rounded MyDecimal 433 err := dec.Round(&rounded, ca.scale, ModeTruncate) 434 c.Check(err, Equals, ca.err) 435 result := rounded.ToString() 436 c.Check(string(result), Equals, ca.output) 437 } 438 } 439 440 func (s *testMyDecimalSuite) TestRoundWithCeil(c *C) { 441 tests := []struct { 442 input string 443 scale int 444 output string 445 err error 446 }{ 447 {"123456789.987654321", 1, "123456790.0", nil}, 448 {"15.1", 0, "16", nil}, 449 {"15.5", 0, "16", nil}, 450 {"15.9", 0, "16", nil}, 451 //TODO:fix me 452 {"-15.1", 0, "-16", nil}, 453 {"-15.5", 0, "-16", nil}, 454 {"-15.9", 0, "-16", nil}, 455 {"15.1", 1, "15.1", nil}, 456 {"-15.1", 1, "-15.1", nil}, 457 {"15.17", 1, "15.2", nil}, 458 {"15.4", -1, "20", nil}, 459 {"-15.4", -1, "-20", nil}, 460 {"5.4", -1, "10", nil}, 461 {".999", 0, "1", nil}, 462 {"999999999", -9, "1000000000", nil}, 463 } 464 for _, ca := range tests { 465 var dec MyDecimal 466 dec.FromString([]byte(ca.input)) 467 var rounded MyDecimal 468 err := dec.Round(&rounded, ca.scale, modeCeiling) 469 c.Check(err, Equals, ca.err) 470 result := rounded.ToString() 471 c.Check(string(result), Equals, ca.output) 472 } 473 } 474 475 func (s *testMyDecimalSuite) TestFromString(c *C) { 476 type tcase struct { 477 input string 478 output string 479 err error 480 } 481 tests := []tcase{ 482 {"12345", "12345", nil}, 483 {"12345.", "12345", nil}, 484 {"123.45.", "123.45", nil}, 485 {"-123.45.", "-123.45", nil}, 486 {".00012345000098765", "0.00012345000098765", nil}, 487 {".12345000098765", "0.12345000098765", nil}, 488 {"-.000000012345000098765", "-0.000000012345000098765", nil}, 489 {"1234500009876.5", "1234500009876.5", nil}, 490 {"123E5", "12300000", nil}, 491 {"123E-2", "1.23", nil}, 492 {"1e1073741823", "999999999999999999999999999999999999999999999999999999999999999999999999999999999", ErrOverflow}, 493 {"-1e1073741823", "-999999999999999999999999999999999999999999999999999999999999999999999999999999999", ErrOverflow}, 494 {"1e18446744073709551620", "0", ErrBadNumber}, 495 {"1e", "1", ErrTruncated}, 496 {"1e001", "10", nil}, 497 {"1e00", "1", nil}, 498 {"1eabc", "1", ErrTruncated}, 499 {"1e 1dddd ", "10", ErrTruncated}, 500 {"1e - 1", "1", ErrTruncated}, 501 {"1e -1", "0.1", nil}, 502 } 503 for _, ca := range tests { 504 var dec MyDecimal 505 err := dec.FromString([]byte(ca.input)) 506 c.Check(err, Equals, ca.err, Commentf("input: %s", ca.input)) 507 result := dec.ToString() 508 c.Check(string(result), Equals, ca.output, Commentf("dec:%s", dec.String())) 509 } 510 wordBufLen = 1 511 tests = []tcase{ 512 {"123450000098765", "98765", ErrOverflow}, 513 {"123450.000098765", "123450", ErrTruncated}, 514 } 515 for _, ca := range tests { 516 var dec MyDecimal 517 err := dec.FromString([]byte(ca.input)) 518 c.Check(err, Equals, ca.err) 519 result := dec.ToString() 520 c.Check(string(result), Equals, ca.output, Commentf("dec:%s", dec.String())) 521 } 522 wordBufLen = maxWordBufLen 523 } 524 525 func (s *testMyDecimalSuite) TestToString(c *C) { 526 type tcase struct { 527 input string 528 output string 529 } 530 tests := []tcase{ 531 {"123.123", "123.123"}, 532 {"123.1230", "123.1230"}, 533 {"00123.123", "123.123"}, 534 } 535 for _, ca := range tests { 536 var dec MyDecimal 537 dec.FromString([]byte(ca.input)) 538 result := dec.ToString() 539 c.Check(string(result), Equals, ca.output) 540 } 541 } 542 543 func (s *testMyDecimalSuite) TestToBinFromBin(c *C) { 544 type tcase struct { 545 input string 546 precision int 547 frac int 548 output string 549 err error 550 } 551 tests := []tcase{ 552 {"-10.55", 4, 2, "-10.55", nil}, 553 {"0.0123456789012345678912345", 30, 25, "0.0123456789012345678912345", nil}, 554 {"12345", 5, 0, "12345", nil}, 555 {"12345", 10, 3, "12345.000", nil}, 556 {"123.45", 10, 3, "123.450", nil}, 557 {"-123.45", 20, 10, "-123.4500000000", nil}, 558 {".00012345000098765", 15, 14, "0.00012345000098", ErrTruncated}, 559 {".00012345000098765", 22, 20, "0.00012345000098765000", nil}, 560 {".12345000098765", 30, 20, "0.12345000098765000000", nil}, 561 {"-.000000012345000098765", 30, 20, "-0.00000001234500009876", ErrTruncated}, 562 {"1234500009876.5", 30, 5, "1234500009876.50000", nil}, 563 {"111111111.11", 10, 2, "11111111.11", ErrOverflow}, 564 {"000000000.01", 7, 3, "0.010", nil}, 565 {"123.4", 10, 2, "123.40", nil}, 566 {"1000", 3, 0, "0", ErrOverflow}, 567 } 568 for _, ca := range tests { 569 var dec MyDecimal 570 err := dec.FromString([]byte(ca.input)) 571 c.Assert(err, IsNil) 572 buf, err := dec.ToBin(ca.precision, ca.frac) 573 c.Assert(err, Equals, ca.err, Commentf(ca.input)) 574 var dec2 MyDecimal 575 _, err = dec2.FromBin(buf, ca.precision, ca.frac) 576 c.Assert(err, IsNil) 577 str := dec2.ToString() 578 c.Assert(string(str), Equals, ca.output) 579 } 580 var dec MyDecimal 581 dec.FromInt(1) 582 errTests := []struct { 583 prec int 584 frac int 585 }{ 586 {82, 1}, 587 {-1, 1}, 588 {10, 31}, 589 {10, -1}, 590 } 591 for _, tt := range errTests { 592 _, err := dec.ToBin(tt.prec, tt.frac) 593 c.Assert(ErrBadNumber.Equal(err), IsTrue) 594 } 595 } 596 597 func (s *testMyDecimalSuite) TestCompare(c *C) { 598 type tcase struct { 599 a string 600 b string 601 cmp int 602 } 603 tests := []tcase{ 604 {"12", "13", -1}, 605 {"13", "12", 1}, 606 {"-10", "10", -1}, 607 {"10", "-10", 1}, 608 {"-12", "-13", 1}, 609 {"0", "12", -1}, 610 {"-10", "0", -1}, 611 {"4", "4", 0}, 612 {"-1.1", "-1.2", 1}, 613 {"1.2", "1.1", 1}, 614 {"1.1", "1.2", -1}, 615 } 616 for _, tt := range tests { 617 var a, b MyDecimal 618 a.FromString([]byte(tt.a)) 619 b.FromString([]byte(tt.b)) 620 c.Assert(a.Compare(&b), Equals, tt.cmp) 621 } 622 } 623 624 func (s *testMyDecimalSuite) TestMaxDecimal(c *C) { 625 type tcase struct { 626 prec int 627 frac int 628 result string 629 } 630 tests := []tcase{ 631 {1, 1, "0.9"}, 632 {1, 0, "9"}, 633 {2, 1, "9.9"}, 634 {4, 2, "99.99"}, 635 {6, 3, "999.999"}, 636 {8, 4, "9999.9999"}, 637 {10, 5, "99999.99999"}, 638 {12, 6, "999999.999999"}, 639 {14, 7, "9999999.9999999"}, 640 {16, 8, "99999999.99999999"}, 641 {18, 9, "999999999.999999999"}, 642 {20, 10, "9999999999.9999999999"}, 643 {20, 20, "0.99999999999999999999"}, 644 {20, 0, "99999999999999999999"}, 645 {40, 20, "99999999999999999999.99999999999999999999"}, 646 } 647 for _, tt := range tests { 648 var dec MyDecimal 649 maxDecimal(tt.prec, tt.frac, &dec) 650 str := dec.ToString() 651 c.Assert(string(str), Equals, tt.result) 652 } 653 } 654 655 func (s *testMyDecimalSuite) TestNeg(c *C) { 656 type testCase struct { 657 a string 658 result string 659 err error 660 } 661 tests := []testCase{ 662 {"-0.0000000000000000000000000000000000000000000000000017382578996420603", "0.0000000000000000000000000000000000000000000000000017382578996420603", nil}, 663 {"-13890436710184412000000000000000000000000000000000000000000000000000000000000", "13890436710184412000000000000000000000000000000000000000000000000000000000000", nil}, 664 {"0", "0", nil}, 665 } 666 for _, tt := range tests { 667 a := NewDecFromStringForTest(tt.a) 668 negResult := DecimalNeg(a) 669 result := negResult.ToString() 670 c.Assert(string(result), Equals, tt.result) 671 } 672 } 673 674 func (s *testMyDecimalSuite) TestAdd(c *C) { 675 type testCase struct { 676 a string 677 b string 678 result string 679 err error 680 } 681 tests := []testCase{ 682 {".00012345000098765", "123.45", "123.45012345000098765", nil}, 683 {".1", ".45", "0.55", nil}, 684 {"1234500009876.5", ".00012345000098765", "1234500009876.50012345000098765", nil}, 685 {"9999909999999.5", ".555", "9999910000000.055", nil}, 686 {"99999999", "1", "100000000", nil}, 687 {"989999999", "1", "990000000", nil}, 688 {"999999999", "1", "1000000000", nil}, 689 {"12345", "123.45", "12468.45", nil}, 690 {"-12345", "-123.45", "-12468.45", nil}, 691 {"-12345", "123.45", "-12221.55", nil}, 692 {"12345", "-123.45", "12221.55", nil}, 693 {"123.45", "-12345", "-12221.55", nil}, 694 {"-123.45", "12345", "12221.55", nil}, 695 {"5", "-6.0", "-1.0", nil}, 696 {"2" + strings.Repeat("1", 71), strings.Repeat("8", 81), "8888888890" + strings.Repeat("9", 71), nil}, 697 } 698 for _, tt := range tests { 699 a := NewDecFromStringForTest(tt.a) 700 b := NewDecFromStringForTest(tt.b) 701 var sum MyDecimal 702 err := DecimalAdd(a, b, &sum) 703 c.Assert(err, Equals, tt.err) 704 result := sum.ToString() 705 c.Assert(string(result), Equals, tt.result) 706 } 707 } 708 709 func (s *testMyDecimalSuite) TestSub(c *C) { 710 type tcase struct { 711 a string 712 b string 713 result string 714 err error 715 } 716 tests := []tcase{ 717 {".00012345000098765", "123.45", "-123.44987654999901235", nil}, 718 {"1234500009876.5", ".00012345000098765", "1234500009876.49987654999901235", nil}, 719 {"9999900000000.5", ".555", "9999899999999.945", nil}, 720 {"1111.5551", "1111.555", "0.0001", nil}, 721 {".555", ".555", "0", nil}, 722 {"10000000", "1", "9999999", nil}, 723 {"1000001000", ".1", "1000000999.9", nil}, 724 {"1000000000", ".1", "999999999.9", nil}, 725 {"12345", "123.45", "12221.55", nil}, 726 {"-12345", "-123.45", "-12221.55", nil}, 727 {"123.45", "12345", "-12221.55", nil}, 728 {"-123.45", "-12345", "12221.55", nil}, 729 {"-12345", "123.45", "-12468.45", nil}, 730 {"12345", "-123.45", "12468.45", nil}, 731 } 732 for _, tt := range tests { 733 var a, b, sum MyDecimal 734 a.FromString([]byte(tt.a)) 735 b.FromString([]byte(tt.b)) 736 err := DecimalSub(&a, &b, &sum) 737 c.Assert(err, Equals, tt.err) 738 result := sum.ToString() 739 c.Assert(string(result), Equals, tt.result) 740 } 741 } 742 743 func (s *testMyDecimalSuite) TestMul(c *C) { 744 type tcase struct { 745 a string 746 b string 747 result string 748 err error 749 } 750 tests := []tcase{ 751 {"12", "10", "120", nil}, 752 {"-123.456", "98765.4321", "-12193185.1853376", nil}, 753 {"-123456000000", "98765432100000", "-12193185185337600000000000", nil}, 754 {"123456", "987654321", "121931851853376", nil}, 755 {"123456", "9876543210", "1219318518533760", nil}, 756 {"123", "0.01", "1.23", nil}, 757 {"123", "0", "0", nil}, 758 {"-0.0000000000000000000000000000000000000000000000000017382578996420603", "-13890436710184412000000000000000000000000000000000000000000000000000000000000", "0.000000000000000000000000000000", ErrTruncated}, 759 {"1" + strings.Repeat("0", 60), "1" + strings.Repeat("0", 60), "0", ErrOverflow}, 760 {"0.5999991229316", "0.918755041726043", "0.5512522192246113614062276588", nil}, 761 {"0.5999991229317", "0.918755041726042", "0.5512522192247026369112773314", nil}, 762 } 763 for _, tt := range tests { 764 var a, b, product MyDecimal 765 a.FromString([]byte(tt.a)) 766 b.FromString([]byte(tt.b)) 767 err := DecimalMul(&a, &b, &product) 768 c.Check(err, Equals, tt.err) 769 result := product.String() 770 c.Assert(result, Equals, tt.result) 771 } 772 } 773 774 func (s *testMyDecimalSuite) TestDivMod(c *C) { 775 type tcase struct { 776 a string 777 b string 778 result string 779 err error 780 } 781 tests := []tcase{ 782 {"120", "10", "12.000000000", nil}, 783 {"123", "0.01", "12300.000000000", nil}, 784 {"120", "100000000000.00000", "0.000000001200000000", nil}, 785 {"123", "0", "", ErrDivByZero}, 786 {"0", "0", "", ErrDivByZero}, 787 {"-12193185.1853376", "98765.4321", "-123.456000000000000000", nil}, 788 {"121931851853376", "987654321", "123456.000000000", nil}, 789 {"0", "987", "0", nil}, 790 {"1", "3", "0.333333333", nil}, 791 {"1.000000000000", "3", "0.333333333333333333", nil}, 792 {"1", "1", "1.000000000", nil}, 793 {"0.0123456789012345678912345", "9999999999", "0.000000000001234567890246913578148141", nil}, 794 {"10.333000000", "12.34500", "0.837019036046982584042122316", nil}, 795 {"10.000000000060", "2", "5.000000000030000000", nil}, 796 {"51", "0.003430", "14868.804664723032069970", nil}, 797 } 798 for _, tt := range tests { 799 var a, b, to MyDecimal 800 a.FromString([]byte(tt.a)) 801 b.FromString([]byte(tt.b)) 802 err := doDivMod(&a, &b, &to, nil, 5) 803 c.Check(err, Equals, tt.err) 804 if tt.err == ErrDivByZero { 805 continue 806 } 807 result := to.ToString() 808 c.Assert(string(result), Equals, tt.result) 809 } 810 811 tests = []tcase{ 812 {"234", "10", "4", nil}, 813 {"234.567", "10.555", "2.357", nil}, 814 {"-234.567", "10.555", "-2.357", nil}, 815 {"234.567", "-10.555", "2.357", nil}, 816 {"99999999999999999999999999999999999999", "3", "0", nil}, 817 {"51", "0.003430", "0.002760", nil}, 818 {"0.0000000001", "1.0", "0.0000000001", nil}, 819 } 820 for _, tt := range tests { 821 var a, b, to MyDecimal 822 a.FromString([]byte(tt.a)) 823 b.FromString([]byte(tt.b)) 824 ec := doDivMod(&a, &b, nil, &to, 0) 825 c.Check(ec, Equals, tt.err) 826 if tt.err == ErrDivByZero { 827 continue 828 } 829 result := to.ToString() 830 c.Assert(string(result), Equals, tt.result) 831 } 832 833 tests = []tcase{ 834 {"1", "1", "1.0000", nil}, 835 {"1.00", "1", "1.000000", nil}, 836 {"1", "1.000", "1.0000", nil}, 837 {"2", "3", "0.6667", nil}, 838 {"51", "0.003430", "14868.8047", nil}, 839 } 840 for _, tt := range tests { 841 var a, b, to MyDecimal 842 a.FromString([]byte(tt.a)) 843 b.FromString([]byte(tt.b)) 844 ec := DecimalDiv(&a, &b, &to, DivFracIncr) 845 c.Check(ec, Equals, tt.err) 846 if tt.err == ErrDivByZero { 847 continue 848 } 849 c.Assert(to.String(), Equals, tt.result) 850 } 851 852 tests = []tcase{ 853 {"1", "2.0", "1.0", nil}, 854 {"1.0", "2", "1.0", nil}, 855 {"2.23", "3", "2.23", nil}, 856 {"51", "0.003430", "0.002760", nil}, 857 } 858 for _, tt := range tests { 859 var a, b, to MyDecimal 860 a.FromString([]byte(tt.a)) 861 b.FromString([]byte(tt.b)) 862 ec := DecimalMod(&a, &b, &to) 863 c.Check(ec, Equals, tt.err) 864 if tt.err == ErrDivByZero { 865 continue 866 } 867 c.Assert(to.String(), Equals, tt.result) 868 } 869 } 870 871 func (s *testMyDecimalSuite) TestMaxOrMin(c *C) { 872 type tcase struct { 873 neg bool 874 prec int 875 frac int 876 result string 877 } 878 tests := []tcase{ 879 {true, 2, 1, "-9.9"}, 880 {false, 1, 1, "0.9"}, 881 {true, 1, 0, "-9"}, 882 {false, 0, 0, "0"}, 883 {false, 4, 2, "99.99"}, 884 } 885 for _, tt := range tests { 886 dec := NewMaxOrMinDec(tt.neg, tt.prec, tt.frac) 887 c.Assert(dec.String(), Equals, tt.result) 888 } 889 } 890 891 func benchmarkMyDecimalToBinOrHashCases() []string { 892 return []string{ 893 "1.000000000000", "3", "12.000000000", "120", 894 "120000", "100000000000.00000", "0.000000001200000000", 895 "98765.4321", "-123.456000000000000000", 896 "0", "0000000000", "0.00000000000", 897 } 898 } 899 900 func BenchmarkMyDecimalToBin(b *testing.B) { 901 cases := benchmarkMyDecimalToBinOrHashCases() 902 decs := make([]*MyDecimal, 0, len(cases)) 903 for _, ca := range cases { 904 var dec MyDecimal 905 if err := dec.FromString([]byte(ca)); err != nil { 906 b.Fatal(err) 907 } 908 decs = append(decs, &dec) 909 } 910 911 b.ResetTimer() 912 for i := 0; i < b.N; i++ { 913 for _, dec := range decs { 914 prec, frac := dec.PrecisionAndFrac() 915 _, err := dec.ToBin(prec, frac) 916 if err != nil { 917 b.Fatal(err) 918 } 919 } 920 } 921 } 922 923 func BenchmarkMyDecimalToHashKey(b *testing.B) { 924 cases := benchmarkMyDecimalToBinOrHashCases() 925 decs := make([]*MyDecimal, 0, len(cases)) 926 for _, ca := range cases { 927 var dec MyDecimal 928 if err := dec.FromString([]byte(ca)); err != nil { 929 b.Fatal(err) 930 } 931 decs = append(decs, &dec) 932 } 933 934 b.ResetTimer() 935 for i := 0; i < b.N; i++ { 936 for _, dec := range decs { 937 _, err := dec.ToHashKey() 938 if err != nil { 939 b.Fatal(err) 940 } 941 } 942 } 943 }