github.com/Finschia/finschia-sdk@v0.48.1/types/decimal_test.go (about) 1 package types_test 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 "strings" 9 "testing" 10 11 "github.com/stretchr/testify/suite" 12 "gopkg.in/yaml.v2" 13 14 sdk "github.com/Finschia/finschia-sdk/types" 15 ) 16 17 type decimalTestSuite struct { 18 suite.Suite 19 } 20 21 func TestDecimalTestSuite(t *testing.T) { 22 suite.Run(t, new(decimalTestSuite)) 23 } 24 25 // create a decimal from a decimal string (ex. "1234.5678") 26 func (s *decimalTestSuite) mustNewDecFromStr(str string) (d sdk.Dec) { 27 d, err := sdk.NewDecFromStr(str) 28 s.Require().NoError(err) 29 30 return d 31 } 32 33 func (s *decimalTestSuite) TestNewDecFromStr() { 34 largeBigInt, ok := new(big.Int).SetString("3144605511029693144278234343371835", 10) 35 s.Require().True(ok) 36 37 largerBigInt, ok := new(big.Int).SetString("8888888888888888888888888888888888888888888888888888888888888888888844444440", 10) 38 s.Require().True(ok) 39 40 largestBigInt, ok := new(big.Int).SetString("33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) 41 s.Require().True(ok) 42 43 tests := []struct { 44 decimalStr string 45 expErr bool 46 exp sdk.Dec 47 }{ 48 {"", true, sdk.Dec{}}, 49 {"0.-75", true, sdk.Dec{}}, 50 {"0", false, sdk.NewDec(0)}, 51 {"1", false, sdk.NewDec(1)}, 52 {"1.1", false, sdk.NewDecWithPrec(11, 1)}, 53 {"0.75", false, sdk.NewDecWithPrec(75, 2)}, 54 {"0.8", false, sdk.NewDecWithPrec(8, 1)}, 55 {"0.11111", false, sdk.NewDecWithPrec(11111, 5)}, 56 {"314460551102969.3144278234343371835", true, sdk.NewDec(3141203149163817869)}, 57 { 58 "314460551102969314427823434337.1835718092488231350", 59 true, sdk.NewDecFromBigIntWithPrec(largeBigInt, 4), 60 }, 61 { 62 "314460551102969314427823434337.1835", 63 false, sdk.NewDecFromBigIntWithPrec(largeBigInt, 4), 64 }, 65 {".", true, sdk.Dec{}}, 66 {".0", true, sdk.NewDec(0)}, 67 {"1.", true, sdk.NewDec(1)}, 68 {"foobar", true, sdk.Dec{}}, 69 {"0.foobar", true, sdk.Dec{}}, 70 {"0.foobar.", true, sdk.Dec{}}, 71 {"8888888888888888888888888888888888888888888888888888888888888888888844444440", false, sdk.NewDecFromBigInt(largerBigInt)}, 72 {"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535", false, sdk.NewDecFromBigIntWithPrec(largestBigInt, 18)}, 73 {"133499189745056880149688856635597007162669032647290798121690100488888732861291", true, sdk.Dec{}}, 74 } 75 76 for tcIndex, tc := range tests { 77 res, err := sdk.NewDecFromStr(tc.decimalStr) 78 if tc.expErr { 79 s.Require().NotNil(err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex) 80 } else { 81 s.Require().Nil(err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex) 82 s.Require().True(res.Equal(tc.exp), "equality was incorrect, res %v, exp %v, tc %v", res, tc.exp, tcIndex) 83 } 84 85 // negative tc 86 res, err = sdk.NewDecFromStr("-" + tc.decimalStr) 87 if tc.expErr { 88 s.Require().NotNil(err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex) 89 } else { 90 s.Require().Nil(err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex) 91 exp := tc.exp.Mul(sdk.NewDec(-1)) 92 s.Require().True(res.Equal(exp), "equality was incorrect, res %v, exp %v, tc %v", res, exp, tcIndex) 93 } 94 } 95 } 96 97 func (s *decimalTestSuite) TestDecString() { 98 tests := []struct { 99 d sdk.Dec 100 want string 101 }{ 102 {sdk.NewDec(0), "0.000000000000000000"}, 103 {sdk.NewDec(1), "1.000000000000000000"}, 104 {sdk.NewDec(10), "10.000000000000000000"}, 105 {sdk.NewDec(12340), "12340.000000000000000000"}, 106 {sdk.NewDecWithPrec(12340, 4), "1.234000000000000000"}, 107 {sdk.NewDecWithPrec(12340, 5), "0.123400000000000000"}, 108 {sdk.NewDecWithPrec(12340, 8), "0.000123400000000000"}, 109 {sdk.NewDecWithPrec(1009009009009009009, 17), "10.090090090090090090"}, 110 } 111 for tcIndex, tc := range tests { 112 s.Require().Equal(tc.want, tc.d.String(), "bad String(), index: %v", tcIndex) 113 } 114 } 115 116 func (s *decimalTestSuite) TestDecFloat64() { 117 tests := []struct { 118 d sdk.Dec 119 want float64 120 }{ 121 {sdk.NewDec(0), 0.000000000000000000}, 122 {sdk.NewDec(1), 1.000000000000000000}, 123 {sdk.NewDec(10), 10.000000000000000000}, 124 {sdk.NewDec(12340), 12340.000000000000000000}, 125 {sdk.NewDecWithPrec(12340, 4), 1.234000000000000000}, 126 {sdk.NewDecWithPrec(12340, 5), 0.123400000000000000}, 127 {sdk.NewDecWithPrec(12340, 8), 0.000123400000000000}, 128 {sdk.NewDecWithPrec(1009009009009009009, 17), 10.090090090090090090}, 129 } 130 for tcIndex, tc := range tests { 131 value, err := tc.d.Float64() 132 s.Require().Nil(err, "error getting Float64(), index: %v", tcIndex) 133 s.Require().Equal(tc.want, value, "bad Float64(), index: %v", tcIndex) 134 s.Require().Equal(tc.want, tc.d.MustFloat64(), "bad MustFloat64(), index: %v", tcIndex) 135 } 136 } 137 138 func (s *decimalTestSuite) TestEqualities() { 139 tests := []struct { 140 d1, d2 sdk.Dec 141 gt, lt, eq bool 142 }{ 143 {sdk.NewDec(0), sdk.NewDec(0), false, false, true}, 144 {sdk.NewDecWithPrec(0, 2), sdk.NewDecWithPrec(0, 4), false, false, true}, 145 {sdk.NewDecWithPrec(100, 0), sdk.NewDecWithPrec(100, 0), false, false, true}, 146 {sdk.NewDecWithPrec(-100, 0), sdk.NewDecWithPrec(-100, 0), false, false, true}, 147 {sdk.NewDecWithPrec(-1, 1), sdk.NewDecWithPrec(-1, 1), false, false, true}, 148 {sdk.NewDecWithPrec(3333, 3), sdk.NewDecWithPrec(3333, 3), false, false, true}, 149 150 {sdk.NewDecWithPrec(0, 0), sdk.NewDecWithPrec(3333, 3), false, true, false}, 151 {sdk.NewDecWithPrec(0, 0), sdk.NewDecWithPrec(100, 0), false, true, false}, 152 {sdk.NewDecWithPrec(-1, 0), sdk.NewDecWithPrec(3333, 3), false, true, false}, 153 {sdk.NewDecWithPrec(-1, 0), sdk.NewDecWithPrec(100, 0), false, true, false}, 154 {sdk.NewDecWithPrec(1111, 3), sdk.NewDecWithPrec(100, 0), false, true, false}, 155 {sdk.NewDecWithPrec(1111, 3), sdk.NewDecWithPrec(3333, 3), false, true, false}, 156 {sdk.NewDecWithPrec(-3333, 3), sdk.NewDecWithPrec(-1111, 3), false, true, false}, 157 158 {sdk.NewDecWithPrec(3333, 3), sdk.NewDecWithPrec(0, 0), true, false, false}, 159 {sdk.NewDecWithPrec(100, 0), sdk.NewDecWithPrec(0, 0), true, false, false}, 160 {sdk.NewDecWithPrec(3333, 3), sdk.NewDecWithPrec(-1, 0), true, false, false}, 161 {sdk.NewDecWithPrec(100, 0), sdk.NewDecWithPrec(-1, 0), true, false, false}, 162 {sdk.NewDecWithPrec(100, 0), sdk.NewDecWithPrec(1111, 3), true, false, false}, 163 {sdk.NewDecWithPrec(3333, 3), sdk.NewDecWithPrec(1111, 3), true, false, false}, 164 {sdk.NewDecWithPrec(-1111, 3), sdk.NewDecWithPrec(-3333, 3), true, false, false}, 165 } 166 167 for tcIndex, tc := range tests { 168 s.Require().Equal(tc.gt, tc.d1.GT(tc.d2), "GT result is incorrect, tc %d", tcIndex) 169 s.Require().Equal(tc.lt, tc.d1.LT(tc.d2), "LT result is incorrect, tc %d", tcIndex) 170 s.Require().Equal(tc.eq, tc.d1.Equal(tc.d2), "equality result is incorrect, tc %d", tcIndex) 171 } 172 } 173 174 func (s *decimalTestSuite) TestDecsEqual() { 175 tests := []struct { 176 d1s, d2s []sdk.Dec 177 eq bool 178 }{ 179 {[]sdk.Dec{sdk.NewDec(0)}, []sdk.Dec{sdk.NewDec(0)}, true}, 180 {[]sdk.Dec{sdk.NewDec(0)}, []sdk.Dec{sdk.NewDec(1)}, false}, 181 {[]sdk.Dec{sdk.NewDec(0)}, []sdk.Dec{}, false}, 182 {[]sdk.Dec{sdk.NewDec(0), sdk.NewDec(1)}, []sdk.Dec{sdk.NewDec(0), sdk.NewDec(1)}, true}, 183 {[]sdk.Dec{sdk.NewDec(1), sdk.NewDec(0)}, []sdk.Dec{sdk.NewDec(1), sdk.NewDec(0)}, true}, 184 {[]sdk.Dec{sdk.NewDec(1), sdk.NewDec(0)}, []sdk.Dec{sdk.NewDec(0), sdk.NewDec(1)}, false}, 185 {[]sdk.Dec{sdk.NewDec(1), sdk.NewDec(0)}, []sdk.Dec{sdk.NewDec(1)}, false}, 186 {[]sdk.Dec{sdk.NewDec(1), sdk.NewDec(2)}, []sdk.Dec{sdk.NewDec(2), sdk.NewDec(4)}, false}, 187 {[]sdk.Dec{sdk.NewDec(3), sdk.NewDec(18)}, []sdk.Dec{sdk.NewDec(1), sdk.NewDec(6)}, false}, 188 } 189 190 for tcIndex, tc := range tests { 191 s.Require().Equal(tc.eq, sdk.DecsEqual(tc.d1s, tc.d2s), "equality of decional arrays is incorrect, tc %d", tcIndex) 192 s.Require().Equal(tc.eq, sdk.DecsEqual(tc.d2s, tc.d1s), "equality of decional arrays is incorrect (converse), tc %d", tcIndex) 193 } 194 } 195 196 func (s *decimalTestSuite) TestArithmetic() { 197 tests := []struct { 198 d1, d2 sdk.Dec 199 expMul, expMulTruncate sdk.Dec 200 expQuo, expQuoRoundUp, expQuoTruncate sdk.Dec 201 expAdd, expSub sdk.Dec 202 }{ 203 // d1 d2 MUL MulTruncate QUO QUORoundUp QUOTrunctate ADD SUB 204 {sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0)}, 205 {sdk.NewDec(1), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(1), sdk.NewDec(1)}, 206 {sdk.NewDec(0), sdk.NewDec(1), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(1), sdk.NewDec(-1)}, 207 {sdk.NewDec(0), sdk.NewDec(-1), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(-1), sdk.NewDec(1)}, 208 {sdk.NewDec(-1), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(-1), sdk.NewDec(-1)}, 209 210 {sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(2), sdk.NewDec(0)}, 211 {sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(-2), sdk.NewDec(0)}, 212 {sdk.NewDec(1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(0), sdk.NewDec(2)}, 213 {sdk.NewDec(-1), sdk.NewDec(1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(-1), sdk.NewDec(0), sdk.NewDec(-2)}, 214 215 { 216 sdk.NewDec(3), sdk.NewDec(7), sdk.NewDec(21), sdk.NewDec(21), 217 sdk.NewDecWithPrec(428571428571428571, 18), sdk.NewDecWithPrec(428571428571428572, 18), sdk.NewDecWithPrec(428571428571428571, 18), 218 sdk.NewDec(10), sdk.NewDec(-4), 219 }, 220 { 221 sdk.NewDec(2), sdk.NewDec(4), sdk.NewDec(8), sdk.NewDec(8), sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), 222 sdk.NewDec(6), sdk.NewDec(-2), 223 }, 224 225 {sdk.NewDec(100), sdk.NewDec(100), sdk.NewDec(10000), sdk.NewDec(10000), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(200), sdk.NewDec(0)}, 226 227 { 228 sdk.NewDecWithPrec(15, 1), sdk.NewDecWithPrec(15, 1), sdk.NewDecWithPrec(225, 2), sdk.NewDecWithPrec(225, 2), 229 sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(1), sdk.NewDec(3), sdk.NewDec(0), 230 }, 231 { 232 sdk.NewDecWithPrec(3333, 4), sdk.NewDecWithPrec(333, 4), sdk.NewDecWithPrec(1109889, 8), sdk.NewDecWithPrec(1109889, 8), 233 sdk.MustNewDecFromStr("10.009009009009009009"), sdk.MustNewDecFromStr("10.009009009009009010"), sdk.MustNewDecFromStr("10.009009009009009009"), 234 sdk.NewDecWithPrec(3666, 4), sdk.NewDecWithPrec(3, 1), 235 }, 236 } 237 238 for tcIndex, tc := range tests { 239 tc := tc 240 resAdd := tc.d1.Add(tc.d2) 241 resSub := tc.d1.Sub(tc.d2) 242 resMul := tc.d1.Mul(tc.d2) 243 resMulTruncate := tc.d1.MulTruncate(tc.d2) 244 s.Require().True(tc.expAdd.Equal(resAdd), "exp %v, res %v, tc %d", tc.expAdd, resAdd, tcIndex) 245 s.Require().True(tc.expSub.Equal(resSub), "exp %v, res %v, tc %d", tc.expSub, resSub, tcIndex) 246 s.Require().True(tc.expMul.Equal(resMul), "exp %v, res %v, tc %d", tc.expMul, resMul, tcIndex) 247 s.Require().True(tc.expMulTruncate.Equal(resMulTruncate), "exp %v, res %v, tc %d", tc.expMulTruncate, resMulTruncate, tcIndex) 248 249 if tc.d2.IsZero() { // panic for divide by zero 250 s.Require().Panics(func() { tc.d1.Quo(tc.d2) }) 251 } else { 252 resQuo := tc.d1.Quo(tc.d2) 253 s.Require().True(tc.expQuo.Equal(resQuo), "exp %v, res %v, tc %d", tc.expQuo.String(), resQuo.String(), tcIndex) 254 255 resQuoRoundUp := tc.d1.QuoRoundUp(tc.d2) 256 s.Require().True(tc.expQuoRoundUp.Equal(resQuoRoundUp), "exp %v, res %v, tc %d", 257 tc.expQuoRoundUp.String(), resQuoRoundUp.String(), tcIndex) 258 259 resQuoTruncate := tc.d1.QuoTruncate(tc.d2) 260 s.Require().True(tc.expQuoTruncate.Equal(resQuoTruncate), "exp %v, res %v, tc %d", 261 tc.expQuoTruncate.String(), resQuoTruncate.String(), tcIndex) 262 } 263 } 264 } 265 266 func (s *decimalTestSuite) TestBankerRoundChop() { 267 tests := []struct { 268 d1 sdk.Dec 269 exp int64 270 }{ 271 {s.mustNewDecFromStr("0.25"), 0}, 272 {s.mustNewDecFromStr("0"), 0}, 273 {s.mustNewDecFromStr("1"), 1}, 274 {s.mustNewDecFromStr("0.75"), 1}, 275 {s.mustNewDecFromStr("0.5"), 0}, 276 {s.mustNewDecFromStr("7.5"), 8}, 277 {s.mustNewDecFromStr("1.5"), 2}, 278 {s.mustNewDecFromStr("2.5"), 2}, 279 {s.mustNewDecFromStr("0.545"), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even 280 {s.mustNewDecFromStr("1.545"), 2}, 281 } 282 283 for tcIndex, tc := range tests { 284 resNeg := tc.d1.Neg().RoundInt64() 285 s.Require().Equal(-1*tc.exp, resNeg, "negative tc %d", tcIndex) 286 287 resPos := tc.d1.RoundInt64() 288 s.Require().Equal(tc.exp, resPos, "positive tc %d", tcIndex) 289 } 290 } 291 292 func (s *decimalTestSuite) TestTruncate() { 293 tests := []struct { 294 d1 sdk.Dec 295 exp int64 296 }{ 297 {s.mustNewDecFromStr("0"), 0}, 298 {s.mustNewDecFromStr("0.25"), 0}, 299 {s.mustNewDecFromStr("0.75"), 0}, 300 {s.mustNewDecFromStr("1"), 1}, 301 {s.mustNewDecFromStr("1.5"), 1}, 302 {s.mustNewDecFromStr("7.5"), 7}, 303 {s.mustNewDecFromStr("7.6"), 7}, 304 {s.mustNewDecFromStr("7.4"), 7}, 305 {s.mustNewDecFromStr("100.1"), 100}, 306 {s.mustNewDecFromStr("1000.1"), 1000}, 307 } 308 309 for tcIndex, tc := range tests { 310 resNeg := tc.d1.Neg().TruncateInt64() 311 s.Require().Equal(-1*tc.exp, resNeg, "negative tc %d", tcIndex) 312 313 resPos := tc.d1.TruncateInt64() 314 s.Require().Equal(tc.exp, resPos, "positive tc %d", tcIndex) 315 } 316 } 317 318 func (s *decimalTestSuite) TestStringOverflow() { 319 // two random 64 bit primes 320 dec1, err := sdk.NewDecFromStr("51643150036226787134389711697696177267") 321 s.Require().NoError(err) 322 dec2, err := sdk.NewDecFromStr("-31798496660535729618459429845579852627") 323 s.Require().NoError(err) 324 dec3 := dec1.Add(dec2) 325 s.Require().Equal( 326 "19844653375691057515930281852116324640.000000000000000000", 327 dec3.String(), 328 ) 329 } 330 331 func (s *decimalTestSuite) TestDecMulInt() { 332 tests := []struct { 333 sdkDec sdk.Dec 334 sdkInt sdk.Int 335 want sdk.Dec 336 }{ 337 {sdk.NewDec(10), sdk.NewInt(2), sdk.NewDec(20)}, 338 {sdk.NewDec(1000000), sdk.NewInt(100), sdk.NewDec(100000000)}, 339 {sdk.NewDecWithPrec(1, 1), sdk.NewInt(10), sdk.NewDec(1)}, 340 {sdk.NewDecWithPrec(1, 5), sdk.NewInt(20), sdk.NewDecWithPrec(2, 4)}, 341 } 342 for i, tc := range tests { 343 got := tc.sdkDec.MulInt(tc.sdkInt) 344 s.Require().Equal(tc.want, got, "Incorrect result on test case %d", i) 345 } 346 } 347 348 func (s *decimalTestSuite) TestDecCeil() { 349 testCases := []struct { 350 input sdk.Dec 351 expected sdk.Dec 352 }{ 353 {sdk.NewDecWithPrec(1000000000000000, sdk.Precision), sdk.NewDec(1)}, // 0.001 => 1.0 354 {sdk.NewDecWithPrec(-1000000000000000, sdk.Precision), sdk.ZeroDec()}, // -0.001 => 0.0 355 {sdk.ZeroDec(), sdk.ZeroDec()}, // 0.0 => 0.0 356 {sdk.NewDecWithPrec(900000000000000000, sdk.Precision), sdk.NewDec(1)}, // 0.9 => 1.0 357 {sdk.NewDecWithPrec(4001000000000000000, sdk.Precision), sdk.NewDec(5)}, // 4.001 => 5.0 358 {sdk.NewDecWithPrec(-4001000000000000000, sdk.Precision), sdk.NewDec(-4)}, // -4.001 => -4.0 359 {sdk.NewDecWithPrec(4700000000000000000, sdk.Precision), sdk.NewDec(5)}, // 4.7 => 5.0 360 {sdk.NewDecWithPrec(-4700000000000000000, sdk.Precision), sdk.NewDec(-4)}, // -4.7 => -4.0 361 } 362 363 for i, tc := range testCases { 364 res := tc.input.Ceil() 365 s.Require().Equal(tc.expected, res, "unexpected result for test case %d, input: %v", i, tc.input) 366 } 367 } 368 369 func (s *decimalTestSuite) TestPower() { 370 testCases := []struct { 371 input sdk.Dec 372 power uint64 373 expected sdk.Dec 374 }{ 375 {sdk.OneDec(), 10, sdk.OneDec()}, // 1.0 ^ (10) => 1.0 376 {sdk.NewDecWithPrec(5, 1), 2, sdk.NewDecWithPrec(25, 2)}, // 0.5 ^ 2 => 0.25 377 {sdk.NewDecWithPrec(2, 1), 2, sdk.NewDecWithPrec(4, 2)}, // 0.2 ^ 2 => 0.04 378 {sdk.NewDecFromInt(sdk.NewInt(3)), 3, sdk.NewDecFromInt(sdk.NewInt(27))}, // 3 ^ 3 => 27 379 {sdk.NewDecFromInt(sdk.NewInt(-3)), 4, sdk.NewDecFromInt(sdk.NewInt(81))}, // -3 ^ 4 = 81 380 {sdk.NewDecWithPrec(1414213562373095049, 18), 2, sdk.NewDecFromInt(sdk.NewInt(2))}, // 1.414213562373095049 ^ 2 = 2 381 } 382 383 for i, tc := range testCases { 384 res := tc.input.Power(tc.power) 385 s.Require().True(tc.expected.Sub(res).Abs().LTE(sdk.SmallestDec()), "unexpected result for test case %d, input: %v", i, tc.input) 386 } 387 } 388 389 func (s *decimalTestSuite) TestApproxRoot() { 390 testCases := []struct { 391 input sdk.Dec 392 root uint64 393 expected sdk.Dec 394 }{ 395 {sdk.OneDec(), 10, sdk.OneDec()}, // 1.0 ^ (0.1) => 1.0 396 {sdk.NewDecWithPrec(25, 2), 2, sdk.NewDecWithPrec(5, 1)}, // 0.25 ^ (0.5) => 0.5 397 {sdk.NewDecWithPrec(4, 2), 2, sdk.NewDecWithPrec(2, 1)}, // 0.04 ^ (0.5) => 0.2 398 {sdk.NewDecFromInt(sdk.NewInt(27)), 3, sdk.NewDecFromInt(sdk.NewInt(3))}, // 27 ^ (1/3) => 3 399 {sdk.NewDecFromInt(sdk.NewInt(-81)), 4, sdk.NewDecFromInt(sdk.NewInt(-3))}, // -81 ^ (0.25) => -3 400 {sdk.NewDecFromInt(sdk.NewInt(2)), 2, sdk.NewDecWithPrec(1414213562373095049, 18)}, // 2 ^ (0.5) => 1.414213562373095049 401 {sdk.NewDecWithPrec(1005, 3), 31536000, sdk.MustNewDecFromStr("1.000000000158153904")}, // 1.005 ^ (1/31536000) ≈ 1.00000000016 402 {sdk.SmallestDec(), 2, sdk.NewDecWithPrec(1, 9)}, // 1e-18 ^ (0.5) => 1e-9 403 {sdk.SmallestDec(), 3, sdk.MustNewDecFromStr("0.000000999999999997")}, // 1e-18 ^ (1/3) => 1e-6 404 {sdk.NewDecWithPrec(1, 8), 3, sdk.MustNewDecFromStr("0.002154434690031900")}, // 1e-8 ^ (1/3) ≈ 0.00215443469 405 } 406 407 // In the case of 1e-8 ^ (1/3), the result repeats every 5 iterations starting from iteration 24 408 // (i.e. 24, 29, 34, ... give the same result) and never converges enough. The maximum number of 409 // iterations (100) causes the result at iteration 100 to be returned, regardless of convergence. 410 411 for i, tc := range testCases { 412 res, err := tc.input.ApproxRoot(tc.root) 413 s.Require().NoError(err) 414 s.Require().True(tc.expected.Sub(res).Abs().LTE(sdk.SmallestDec()), "unexpected result for test case %d, input: %v", i, tc.input) 415 } 416 } 417 418 func (s *decimalTestSuite) TestApproxSqrt() { 419 testCases := []struct { 420 input sdk.Dec 421 expected sdk.Dec 422 }{ 423 {sdk.OneDec(), sdk.OneDec()}, // 1.0 => 1.0 424 {sdk.NewDecWithPrec(25, 2), sdk.NewDecWithPrec(5, 1)}, // 0.25 => 0.5 425 {sdk.NewDecWithPrec(4, 2), sdk.NewDecWithPrec(2, 1)}, // 0.09 => 0.3 426 {sdk.NewDecFromInt(sdk.NewInt(9)), sdk.NewDecFromInt(sdk.NewInt(3))}, // 9 => 3 427 {sdk.NewDecFromInt(sdk.NewInt(-9)), sdk.NewDecFromInt(sdk.NewInt(-3))}, // -9 => -3 428 {sdk.NewDecFromInt(sdk.NewInt(2)), sdk.NewDecWithPrec(1414213562373095049, 18)}, // 2 => 1.414213562373095049 429 } 430 431 for i, tc := range testCases { 432 res, err := tc.input.ApproxSqrt() 433 s.Require().NoError(err) 434 s.Require().Equal(tc.expected, res, "unexpected result for test case %d, input: %v", i, tc.input) 435 } 436 } 437 438 func (s *decimalTestSuite) TestDecSortableBytes() { 439 tests := []struct { 440 d sdk.Dec 441 want []byte 442 }{ 443 {sdk.NewDec(0), []byte("000000000000000000.000000000000000000")}, 444 {sdk.NewDec(1), []byte("000000000000000001.000000000000000000")}, 445 {sdk.NewDec(10), []byte("000000000000000010.000000000000000000")}, 446 {sdk.NewDec(12340), []byte("000000000000012340.000000000000000000")}, 447 {sdk.NewDecWithPrec(12340, 4), []byte("000000000000000001.234000000000000000")}, 448 {sdk.NewDecWithPrec(12340, 5), []byte("000000000000000000.123400000000000000")}, 449 {sdk.NewDecWithPrec(12340, 8), []byte("000000000000000000.000123400000000000")}, 450 {sdk.NewDecWithPrec(1009009009009009009, 17), []byte("000000000000000010.090090090090090090")}, 451 {sdk.NewDecWithPrec(-1009009009009009009, 17), []byte("-000000000000000010.090090090090090090")}, 452 {sdk.NewDec(1000000000000000000), []byte("max")}, 453 {sdk.NewDec(-1000000000000000000), []byte("--")}, 454 } 455 for tcIndex, tc := range tests { 456 s.Require().Equal(tc.want, sdk.SortableDecBytes(tc.d), "bad String(), index: %v", tcIndex) 457 } 458 459 s.Require().Panics(func() { sdk.SortableDecBytes(sdk.NewDec(1000000000000000001)) }) 460 s.Require().Panics(func() { sdk.SortableDecBytes(sdk.NewDec(-1000000000000000001)) }) 461 } 462 463 func (s *decimalTestSuite) TestDecEncoding() { 464 largestBigInt, ok := new(big.Int).SetString("33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) 465 s.Require().True(ok) 466 467 smallestBigInt, ok := new(big.Int).SetString("-33499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535", 10) 468 s.Require().True(ok) 469 470 const maxDecBitLen = 315 471 maxInt, ok := new(big.Int).SetString(strings.Repeat("1", maxDecBitLen), 2) 472 s.Require().True(ok) 473 474 errMaxInt, ok := new(big.Int).SetString(strings.Repeat("1", maxDecBitLen+1), 2) 475 s.Require().True(ok) 476 477 testCases := []struct { 478 input sdk.Dec 479 rawBz string 480 jsonStr string 481 yamlStr string 482 isErr bool 483 }{ 484 { 485 sdk.NewDec(0), "30", 486 "\"0.000000000000000000\"", 487 "\"0.000000000000000000\"\n", 488 false, 489 }, 490 { 491 sdk.NewDecWithPrec(4, 2), 492 "3430303030303030303030303030303030", 493 "\"0.040000000000000000\"", 494 "\"0.040000000000000000\"\n", 495 false, 496 }, 497 { 498 sdk.NewDecWithPrec(-4, 2), 499 "2D3430303030303030303030303030303030", 500 "\"-0.040000000000000000\"", 501 "\"-0.040000000000000000\"\n", 502 false, 503 }, 504 { 505 sdk.NewDecWithPrec(1414213562373095049, 18), 506 "31343134323133353632333733303935303439", 507 "\"1.414213562373095049\"", 508 "\"1.414213562373095049\"\n", 509 false, 510 }, 511 { 512 sdk.NewDecWithPrec(-1414213562373095049, 18), 513 "2D31343134323133353632333733303935303439", 514 "\"-1.414213562373095049\"", 515 "\"-1.414213562373095049\"\n", 516 false, 517 }, 518 { 519 sdk.NewDecFromBigIntWithPrec(largestBigInt, 18), 520 "3333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", 521 "\"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", 522 "\"33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", 523 false, 524 }, 525 { 526 sdk.NewDecFromBigIntWithPrec(smallestBigInt, 18), 527 "2D3333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", 528 "\"-33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", 529 "\"-33499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", 530 false, 531 }, 532 { 533 sdk.NewDecFromBigIntWithPrec(maxInt, 18), 534 "3636373439353934383732353238343430303734383434343238333137373938353033353831333334353136333233363435333939303630383435303530323434343434333636343330363435303137313838323137353635323136373637", 535 "\"66749594872528440074844428317798503581334516323645399060845050244444366430645.017188217565216767\"", 536 "\"66749594872528440074844428317798503581334516323645399060845050244444366430645.017188217565216767\"\n", 537 false, 538 }, 539 { 540 sdk.NewDecFromBigIntWithPrec(errMaxInt, 18), 541 "313333343939313839373435303536383830313439363838383536363335353937303037313632363639303332363437323930373938313231363930313030343838383838373332383631323930303334333736343335313330343333353335", 542 "\"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"", 543 "\"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535\"\n", 544 true, 545 }, 546 } 547 548 for _, tc := range testCases { 549 bz, err := tc.input.Marshal() 550 s.Require().NoError(err) 551 s.Require().Equal(tc.rawBz, fmt.Sprintf("%X", bz)) 552 553 var other sdk.Dec 554 if tc.isErr { 555 s.Require().Error((&other).Unmarshal(bz)) 556 } else { 557 s.Require().NoError((&other).Unmarshal(bz)) 558 } 559 s.Require().True(tc.input.Equal(other)) 560 561 bz, err = json.Marshal(tc.input) 562 s.Require().NoError(err) 563 s.Require().Equal(tc.jsonStr, string(bz)) 564 if tc.isErr { 565 s.Require().Error(json.Unmarshal(bz, &other)) 566 } else { 567 s.Require().NoError(json.Unmarshal(bz, &other)) 568 } 569 s.Require().True(tc.input.Equal(other)) 570 571 bz, err = yaml.Marshal(tc.input) 572 s.Require().NoError(err) 573 s.Require().Equal(tc.yamlStr, string(bz)) 574 } 575 } 576 577 // Showcase that different orders of operations causes different results. 578 func (s *decimalTestSuite) TestOperationOrders() { 579 n1 := sdk.NewDec(10) 580 n2 := sdk.NewDec(1000000010) 581 s.Require().Equal(n1.Mul(n2).Quo(n2), sdk.NewDec(10)) 582 s.Require().NotEqual(n1.Mul(n2).Quo(n2), n1.Quo(n2).Mul(n2)) 583 } 584 585 func BenchmarkMarshalTo(b *testing.B) { 586 b.ReportAllocs() 587 bis := []struct { 588 in sdk.Dec 589 want []byte 590 }{ 591 { 592 sdk.NewDec(1e8), []byte{ 593 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 594 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 595 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 596 }, 597 }, 598 {sdk.NewDec(0), []byte{0x30}}, 599 } 600 data := make([]byte, 100) 601 602 b.ReportAllocs() 603 b.ResetTimer() 604 605 for i := 0; i < b.N; i++ { 606 for _, bi := range bis { 607 if n, err := bi.in.MarshalTo(data); err != nil { 608 b.Fatal(err) 609 } else { 610 if !bytes.Equal(data[:n], bi.want) { 611 b.Fatalf("Mismatch\nGot: % x\nWant: % x\n", data[:n], bi.want) 612 } 613 } 614 } 615 } 616 }