1 // DecimalTest.cs - NUnit Test Cases for the System.Decimal struct
\r
3 // Author: Martin Weindel (martin.weindel@t-online.de)
\r
5 // (C) Martin Weindel, 2001
\r
8 using NUnit.Framework;
\r
10 using S = System; // for implementation switching only
\r
12 using System.Globalization;
\r
13 using System.Runtime.CompilerServices;
\r
15 namespace MonoTests.System {
\r
17 /// Tests for System.Decimal
\r
19 public class DecimalTest : TestCase
\r
21 public DecimalTest(string name) : base(name) {}
\r
23 public static ITest Suite
\r
25 get { return new TestSuite(typeof(DecimalTest)); }
\r
28 private const int negativeBitValue = unchecked ((int)0x80000000);
\r
29 private const int negativeScale4Value = unchecked ((int)0x80040000);
\r
30 private int [] parts0 = {0,0,0,0}; //Positive Zero.
\r
31 private int [] parts1 = {1,0,0,0};
\r
32 private int [] parts2 = {0,1,0,0};
\r
33 private int [] parts3 = {0,0,1,0};
\r
34 private int [] parts4 = {0,0,0,negativeBitValue}; // Negative zero.
\r
35 private int [] parts5 = {1,1,1,0};
\r
36 private int [] partsMaxValue = {-1,-1,-1,0};
\r
37 private int [] partsMinValue = {-1,-1,-1,negativeBitValue};
\r
38 private int [] parts6 = {1234, 5678, 8888, negativeScale4Value};
\r
40 public void TestToString()
\r
42 NumberFormatInfo nfi = NumberFormatInfo.InvariantInfo;
\r
46 Assert(d.ToString("F", nfi) == "12.35");
\r
47 Assert(d.ToString("F3", nfi) == "12.346");
\r
48 Assert(d.ToString("F0", nfi) == "12");
\r
49 Assert(d.ToString("F7", nfi) == "12.3456780");
\r
50 Assert(d.ToString("E", nfi) == "1.234568E+01");
\r
51 Assert(d.ToString("E3", nfi) == "1.235E+01");
\r
52 Assert(d.ToString("E0", nfi) == "1E+01");
\r
53 Assert(d.ToString("e8", nfi) == "1.23456780e+01");
\r
56 Assert(d.ToString("F", nfi) == "0.00");
\r
57 Assert(d.ToString("F3", nfi) == "0.001");
\r
58 Assert(d.ToString("F0", nfi) == "0");
\r
59 Assert(d.ToString("F6", nfi) == "0.001200");
\r
60 Assert(d.ToString("e", nfi) == "1.200000e-03");
\r
61 Assert(d.ToString("E3", nfi) == "1.200E-03");
\r
62 Assert(d.ToString("E0", nfi) == "1E-03");
\r
63 Assert(d.ToString("E6", nfi) == "1.200000E-03");
\r
66 Assert(d.ToString("F3", nfi) == "-0.001");
\r
67 Assert(d.ToString("F2", nfi) == "-0.00");
\r
68 Assert(d.ToString("F0", nfi) == "-0");
\r
69 Assert(d.ToString("F6", nfi) == "-0.001200");
\r
70 Assert(d.ToString("e3", nfi) == "-1.200e-03");
\r
71 Assert(d.ToString("e", nfi) == "-1.200000e-03");
\r
74 Assert(d.ToString("g", nfi) == "-1.2e-05");
\r
77 Assert(d.ToString("F", nfi) == "-123.00");
\r
78 Assert(d.ToString("F3", nfi) == "-123.000");
\r
79 Assert(d.ToString("F0", nfi) == "-123");
\r
80 Assert(d.ToString("E3", nfi) == "-1.230E+02");
\r
81 Assert(d.ToString("E0", nfi) == "-1E+02");
\r
82 Assert(d.ToString("E", nfi) == "-1.230000E+02");
\r
84 d = S.Decimal.MinValue;
\r
85 Assert(d.ToString("F3", nfi) == "-79228162514264337593543950335.000");
\r
86 Assert(d.ToString("F", nfi) == "-79228162514264337593543950335.00");
\r
87 Assert(d.ToString("F0", nfi) == "-79228162514264337593543950335");
\r
88 Assert(d.ToString("E", nfi) == "-7.922816E+28");
\r
89 Assert(d.ToString("E3", nfi) == "-7.923E+28");
\r
90 Assert(d.ToString("E28", nfi) == "-7.9228162514264337593543950335E+28");
\r
91 Assert(d.ToString("E30", nfi) == "-7.922816251426433759354395033500E+28");
\r
92 Assert(d.ToString("E0", nfi) == "-8E+28");
\r
93 Assert(d.ToString("N3", nfi) == "(79,228,162,514,264,337,593,543,950,335.000)");
\r
94 Assert(d.ToString("N0", nfi) == "(79,228,162,514,264,337,593,543,950,335)");
\r
95 Assert(d.ToString("N", nfi) == "(79,228,162,514,264,337,593,543,950,335.00)");
\r
98 public void TestParse()
\r
100 const int size = 6;
\r
101 string[] stab = new String[size] {
\r
102 "1.2345", "-9876543210", "$ ( 79,228,162,514,264,337,593,543,950,335.000 ) ",
\r
103 "1.234567890e-10", "1.234567890e-24", " 47896396.457983645462346E10 "
\r
105 NumberStyles[] styleTab = new NumberStyles[size] {
\r
106 NumberStyles.Number, NumberStyles.Number, NumberStyles.Currency,
\r
107 NumberStyles.Float, NumberStyles.Float, NumberStyles.Float
\r
110 S.Decimal[] dtab = new S.Decimal[size] {
\r
111 1.2345m, -9876543210m, S.Decimal.MinValue,
\r
112 (S.Decimal)1.234567890e-10, 0.0000000000000000000000012346m, 478963964579836454.62346m
\r
115 for (int i = 0; i < size; i++)
\r
118 d = S.Decimal.Parse(stab[i], styleTab[i], NumberFormatInfo.InvariantInfo);
\r
121 Fail(stab[i] + " != " + d);
\r
126 public void TestConstants()
\r
128 Assert(0m == (decimal)S.Decimal.Zero);
\r
129 Assert(1m == (decimal)S.Decimal.One);
\r
130 Assert(-1m == (decimal)S.Decimal.MinusOne);
\r
131 Assert(0m == (decimal)S.Decimal.Zero);
\r
132 Assert(79228162514264337593543950335m == (decimal)S.Decimal.MaxValue);
\r
133 Assert(-79228162514264337593543950335m == (decimal)S.Decimal.MinValue);
\r
136 public void TestConstructInt32()
\r
138 decimal[] dtab = {0m, 1m, -1m, 123456m, -1234567m};
\r
139 int[] itab = {0, 1, -1, 123456, -1234567};
\r
143 for (int i = 0; i < dtab.GetLength(0); i++)
\r
145 d = new S.Decimal(itab[i]);
\r
146 if ((decimal)d != dtab[i])
\r
148 Fail("Int32 -> Decimal: " + itab[i] + " != " + d);
\r
155 Fail("Decimal -> Int32: " + d + " != " + itab[i]);
\r
160 d = new S.Decimal(Int32.MaxValue);
\r
161 Assert((int)d == Int32.MaxValue);
\r
163 d = new S.Decimal(Int32.MinValue);
\r
164 Assert((int)d == Int32.MinValue);
\r
167 public void TestConstructUInt32()
\r
169 decimal[] dtab = {0m, 1m, 123456m, 123456789m};
\r
170 uint[] itab = {0, 1, 123456, 123456789};
\r
174 for (int i = 0; i < dtab.GetLength(0); i++)
\r
176 d = new S.Decimal(itab[i]);
\r
177 if ((decimal)d != dtab[i])
\r
179 Fail("UInt32 -> Decimal: " + itab[i] + " != " + d);
\r
186 Fail("Decimal -> UInt32: " + d + " != " + itab[i]);
\r
191 d = new S.Decimal(UInt32.MaxValue);
\r
192 Assert((uint)d == UInt32.MaxValue);
\r
194 d = new Decimal(UInt32.MinValue);
\r
195 Assert((uint)d == UInt32.MinValue);
\r
198 public void TestConstructInt64()
\r
200 decimal[] dtab = {0m, 1m, -1m, 9876543m, -9876543210m, 12345678987654321m};
\r
201 long[] itab = {0, 1, -1, 9876543, -9876543210L, 12345678987654321L};
\r
205 for (int i = 0; i < dtab.GetLength(0); i++)
\r
207 d = new S.Decimal(itab[i]);
\r
208 if ((decimal)d != dtab[i])
\r
210 Fail("Int64 -> Decimal: " + itab[i] + " != " + d);
\r
217 Fail("Decimal -> Int64: " + d + " != " + itab[i]);
\r
222 d = new S.Decimal(Int64.MaxValue);
\r
223 Assert((long)d == Int64.MaxValue);
\r
225 d = new Decimal(Int64.MinValue);
\r
226 Assert((long)d == Int64.MinValue);
\r
229 public void TestConstructUInt64()
\r
231 decimal[] dtab = {0m, 1m, 987654321m, 123456789876543210m};
\r
232 ulong[] itab = {0, 1, 987654321, 123456789876543210L};
\r
236 for (int i = 0; i < dtab.GetLength(0); i++)
\r
238 d = new S.Decimal(itab[i]);
\r
239 if ((decimal)d != dtab[i])
\r
241 Fail("UInt64 -> Decimal: " + itab[i] + " != " + d);
\r
245 ulong n = (ulong) d;
\r
248 Fail("Decimal -> UInt64: " + d + " != " + itab[i]);
\r
253 d = new S.Decimal(UInt64.MaxValue);
\r
254 Assert((ulong)d == UInt64.MaxValue);
\r
256 d = new Decimal(UInt64.MinValue);
\r
257 Assert((ulong)d == UInt64.MinValue);
\r
260 public void TestConstructSingle()
\r
264 d = new S.Decimal(-1.2345678f);
\r
265 Assert((decimal)d == -1.234568m);
\r
268 Assert(3.0f == (float)d);
\r
270 d = new S.Decimal(0.0f);
\r
271 Assert((decimal)d == 0m);
\r
272 Assert(0.0f == (float)d);
\r
274 d = new S.Decimal(1.0f);
\r
275 Assert((decimal)d == 1m);
\r
276 Assert(1.0f == (float)d);
\r
278 d = new S.Decimal(-1.2345678f);
\r
279 Assert((decimal)d == -1.234568m);
\r
280 Assert(-1.234568f == (float)d);
\r
282 d = new S.Decimal(1.2345673f);
\r
283 Assert((decimal)d == 1.234567m);
\r
285 d = new S.Decimal(1.2345673e7f);
\r
286 Assert((decimal)d == 12345670m);
\r
288 d = new S.Decimal(1.2345673e-17f);
\r
289 Assert((decimal)d == 0.00000000000000001234567m);
\r
290 Assert(1.234567e-17f == (float)d);
\r
295 d = new S.Decimal(Single.MaxValue);
\r
298 catch (OverflowException)
\r
304 d = new S.Decimal(Single.NaN);
\r
307 catch (OverflowException)
\r
313 d = new S.Decimal(Single.PositiveInfinity);
\r
316 catch (OverflowException)
\r
321 public void TestConstructSingleRounding()
\r
325 d = new S.Decimal(1765.2356f);
\r
326 Assert(d == 1765.236m);
\r
328 d = new S.Decimal(1765.23554f);
\r
329 Assert("failed banker's rule rounding test 1", d == 1765.236m);
\r
331 d = new S.Decimal(1765.2354f);
\r
332 Assert(d == 1765.235m);
\r
334 d = new S.Decimal(1765.2346f);
\r
335 Assert(d == 1765.235m);
\r
337 d = new S.Decimal(1765.23454f);
\r
338 Assert("failed banker's rule rounding test 2", d == 1765.234m);
\r
340 d = new S.Decimal(1765.2344f);
\r
341 Assert(d == 1765.234m);
\r
343 d = new S.Decimal(0.00017652356f);
\r
344 Assert(d == 0.0001765236m);
\r
346 d = new S.Decimal(0.000176523554f);
\r
347 Assert("failed banker's rule rounding test 3", d == 0.0001765236m);
\r
349 d = new S.Decimal(0.00017652354f);
\r
350 Assert(d == 0.0001765235m);
\r
352 d = new S.Decimal(0.00017652346f);
\r
353 Assert(d == 0.0001765235m);
\r
355 d = new S.Decimal(0.000176523454f);
\r
356 Assert("failed banker's rule rounding test 4", d == 0.0001765234m);
\r
358 d = new S.Decimal(0.00017652344f);
\r
359 Assert(d == 0.0001765234m);
\r
361 d = new S.Decimal(3.7652356e10f);
\r
362 Assert(d == 37652360000m);
\r
364 d = new S.Decimal(3.7652356e20f);
\r
365 Assert(d == 376523600000000000000m);
\r
367 d = new S.Decimal(3.76523554e20f);
\r
368 Assert("failed banker's rule rounding test 5", d == 376523600000000000000m);
\r
370 d = new S.Decimal(3.7652352e20f);
\r
371 Assert(d == 376523500000000000000m);
\r
373 d = new S.Decimal(3.7652348e20f);
\r
374 Assert(d == 376523500000000000000m);
\r
376 d = new S.Decimal(3.76523454e20f);
\r
377 Assert("failed banker's rule rounding test 6", d == 376523400000000000000m);
\r
379 d = new S.Decimal(3.7652342e20f);
\r
380 Assert(d == 376523400000000000000m);
\r
383 public void TestConstructDouble()
\r
387 d = new S.Decimal(0.0);
\r
388 Assert((decimal)d == 0m);
\r
390 d = new S.Decimal(1.0);
\r
391 Assert((decimal)d == 1m);
\r
392 Assert(1.0 == (double)d);
\r
394 d = new S.Decimal(-1.2345678901234);
\r
395 Assert((decimal)d == -1.2345678901234m);
\r
396 Assert(-1.2345678901234 == (double)d);
\r
398 d = new S.Decimal(1.2345678901234);
\r
399 Assert((decimal)d == 1.2345678901234m);
\r
401 d = new S.Decimal(1.2345678901234e8);
\r
402 Assert((decimal)d == 123456789.01234m);
\r
403 Assert(1.2345678901234e8 == (double)d);
\r
405 d = new S.Decimal(1.2345678901234e16);
\r
406 Assert((decimal)d == 12345678901234000m);
\r
407 Assert(1.2345678901234e16 == (double)d);
\r
409 d = new S.Decimal(1.2345678901234e24);
\r
410 Assert((decimal)d == 1234567890123400000000000m);
\r
411 Assert(1.2345678901234e24 == (double)d);
\r
413 d = new S.Decimal(1.2345678901234e28);
\r
414 Assert((decimal)d == 1.2345678901234e28m);
\r
415 Assert(1.2345678901234e28 == (double)d);
\r
417 d = new S.Decimal(7.2345678901234e28);
\r
418 Assert((decimal)d == 7.2345678901234e28m);
\r
419 Assert(new S.Decimal((double)d) == d);
\r
421 d = new S.Decimal(1.2345678901234e-8);
\r
422 Assert((decimal)d == 1.2345678901234e-8m);
\r
424 d = new S.Decimal(1.2345678901234e-14);
\r
425 Assert((decimal)d == 1.2345678901234e-14m);
\r
426 Assert(1.2345678901234e-14 == (double)d);
\r
428 d = new S.Decimal(1.2342278901234e-25);
\r
429 Assert((decimal)d == 1.234e-25m);
\r
434 d = new S.Decimal(8e28);
\r
437 catch (OverflowException)
\r
443 d = new S.Decimal(8e48);
\r
446 catch (OverflowException)
\r
452 d = new S.Decimal(Double.NaN);
\r
455 catch (OverflowException)
\r
461 d = new S.Decimal(Double.PositiveInfinity);
\r
464 catch (OverflowException)
\r
469 public void TestConstructDoubleRound()
\r
473 d = new S.Decimal(1765.231234567857);
\r
474 Assert(d == 1765.23123456786m);
\r
476 d = new S.Decimal(1765.2312345678554);
\r
477 Assert("failed banker's rule rounding test 1", d == 1765.23123456786m);
\r
478 Assert(1765.23123456786 == (double)d);
\r
480 d = new S.Decimal(1765.231234567853);
\r
481 Assert(d == 1765.23123456785m);
\r
483 d = new S.Decimal(1765.231234567847);
\r
484 Assert(d == 1765.23123456785m);
\r
486 d = new S.Decimal(1765.231234567843);
\r
487 Assert(d == 1765.23123456784m);
\r
489 d = new S.Decimal(1.765231234567857e-9);
\r
490 Assert(d == 1.76523123456786e-9m);
\r
492 d = new S.Decimal(1.7652312345678554e-9);
\r
493 Assert("failed banker's rule rounding test 3", d == 1.76523123456786e-9m);
\r
495 d = new S.Decimal(1.765231234567853e-9);
\r
496 Assert(d == 1.76523123456785e-9m);
\r
498 d = new S.Decimal(1.765231234567857e+24);
\r
499 Assert(d == 1.76523123456786e+24m);
\r
501 d = new S.Decimal(1.7652312345678554e+24);
\r
502 Assert("failed banker's rule rounding test 4", d == 1.76523123456786e+24m);
\r
504 d = new S.Decimal(1.765231234567853e+24);
\r
505 Assert(d == 1.76523123456785e+24m);
\r
508 public void TestConstructDoubleRoundHard()
\r
512 d = new S.Decimal(1765.2312345678454);
\r
513 // this case fails in Microsoft implementation
\r
514 // but it conforms to specification (rounding 15 digits according to banker's rule)
\r
515 Assert("failed banker's rule rounding test 2", d == 1765.23123456784m);
\r
518 public void TestNegate()
\r
522 d = new S.Decimal(12345678);
\r
523 Assert((decimal)S.Decimal.Negate(d) == -12345678m);
\r
526 public void TestPartConstruct()
\r
530 d = new Decimal(parts0);
\r
533 d = new Decimal(parts1);
\r
536 d = new Decimal(parts2);
\r
537 Assert(d == 4294967296m);
\r
539 d = new Decimal(parts3);
\r
540 Assert(d == 18446744073709551616m);
\r
542 d = new Decimal(parts4);
\r
545 d = new Decimal(parts5);
\r
546 Assert(d == 18446744078004518913m);
\r
548 d = new Decimal(partsMaxValue);
\r
549 Assert(d == Decimal.MaxValue);
\r
551 d = new Decimal(partsMinValue);
\r
552 Assert(d == Decimal.MinValue);
\r
554 d = new Decimal(parts6);
\r
555 int[] erg = Decimal.GetBits(d);
\r
556 for (int i = 0; i < 4; i++)
\r
558 Assert(erg[i] == parts6[i]);
\r
562 public void TestFloorTruncate()
\r
564 decimal[,] dtab = {
\r
565 {0m, 0m, 0m}, {1m, 1m, 1m}, {-1m, -1m, -1m}, {1.1m, 1m, 1m},
\r
566 {-1.000000000001m, -2m, -1m}, {12345.67890m,12345m,12345m},
\r
567 {-123456789012345.67890m, -123456789012346m, -123456789012345m},
\r
568 {S.Decimal.MaxValue, S.Decimal.MaxValue, S.Decimal.MaxValue},
\r
569 {S.Decimal.MinValue, S.Decimal.MinValue, S.Decimal.MinValue},
\r
570 {6.999999999m, 6m, 6m}, {-6.999999999m, -7m, -6m},
\r
571 {0.00001m, 0m, 0m}, {-0.00001m, -1m, 0m}
\r
576 for (int i = 0; i < dtab.GetLength(0); i++)
\r
578 d = S.Decimal.Floor(dtab[i,0]);
\r
579 if (d != dtab[i,1])
\r
581 Fail("Floor: Floor(" + dtab[i,0] + ") != " + d);
\r
583 d = S.Decimal.Truncate(dtab[i,0]);
\r
584 if (d != dtab[i,2])
\r
586 Fail("Truncate: Truncate(" + dtab[i,0] + ") != " + d);
\r
591 public void TestRound()
\r
593 decimal[,] dtab = {
\r
594 {1m, 0, 1m}, {1.234567890m, 1, 1.2m},
\r
595 {1.234567890m, 2, 1.23m}, {1.23450000001m, 3, 1.235m},
\r
596 {1.2345m, 3, 1.234m}, {1.2355m, 3, 1.236m},
\r
597 {1.234567890m, 4, 1.2346m}, {1.23567890m, 2, 1.24m},
\r
598 {47893764694.4578563236436621m, 7, 47893764694.4578563m},
\r
599 {-47893764694.4578563236436621m, 9, -47893764694.457856324m},
\r
600 {-47893764694.4578m, 5, -47893764694.4578m}
\r
605 for (int i = 0; i < dtab.GetLength(0); i++)
\r
607 d = S.Decimal.Round(dtab[i,0], (int)dtab[i,1]);
\r
608 if (d != dtab[i,2])
\r
610 Fail("Round: Round(" + dtab[i,0] + "," + (int)dtab[i,1] + ") != " + d);
\r