4 // Represents a floating-point decimal data type with up to 29
5 // significant digits, suitable for financial and commercial calculations.
8 // Martin Weindel (martin.weindel@t-online.de)
10 // (C) 2001 Martin Weindel
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Globalization;
39 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
48 /// Represents a floating-point decimal data type with up to 29 significant
49 /// digits, suitable for financial and commercial calculations
52 public struct Decimal: IFormattable, IConvertible,
54 IComparable, IComparable<Decimal>
59 #if BOOTSTRAP_WITH_OLDLIB
61 // LAMESPEC: the attributes aren't mentioned, but show up in CorCompare
62 // Unfortunately, corcompare starts throwing security exceptions when
63 // these attributes are present...
65 [DecimalConstantAttribute(0, 1, unchecked((uint)-1), unchecked((uint)-1), unchecked((uint)-1))]
66 public static readonly Decimal MinValue = new Decimal(-1, -1, -1, true, 0);
67 [DecimalConstantAttribute(0, 0, unchecked((uint)-1), unchecked((uint)-1), unchecked((uint)-1))]
68 public static readonly Decimal MaxValue = new Decimal(-1, -1, -1, false, 0);
69 [DecimalConstantAttribute(0, 1, 0, 0, 1)]
70 public static readonly Decimal MinusOne = new Decimal(1, 0, 0, true, 0);
71 [DecimalConstantAttribute(0, 0, 0, 0, 1)]
72 public static readonly Decimal One = new Decimal(1, 0, 0, false, 0);
73 [DecimalConstantAttribute(0, 0, 0, 0, 0)]
74 public static readonly Decimal Zero = new Decimal(0, 0, 0, false, 0);
76 public const decimal MinValue = -79228162514264337593543950335m;
77 public const decimal MaxValue = 79228162514264337593543950335m;
79 public const decimal MinusOne = -1;
80 public const decimal One = 1;
81 public const decimal Zero = 0;
84 private static readonly Decimal MaxValueDiv10 = MaxValue / 10;
86 // maximal decimal value as double
87 private static readonly double dDecMaxValue = 7.922816251426433759354395033e28;
88 // epsilon decimal value as double
89 private static readonly double dDecEpsilon = 0.5e-28; // == 0.5 * 1 / 10^28
92 private const int DECIMAL_DIVIDE_BY_ZERO = 5;
93 private const uint MAX_SCALE = 28;
94 private const int iMAX_SCALE = 28;
95 private const uint SIGN_FLAG = 0x80000000;
96 private const uint SCALE_MASK = 0x00FF0000;
97 private const int SCALE_SHIFT = 16;
98 private const uint RESERVED_SS32_BITS = 0x7F00FFFF;
100 // internal representation of decimal
106 public Decimal(int lo, int mid, int hi, bool isNegative, byte scale)
114 if (scale > MAX_SCALE)
116 throw new ArgumentOutOfRangeException (Locale.GetText ("scale must be between 0 and 28"));
120 ss32 <<= SCALE_SHIFT;
121 if (isNegative) ss32 |= SIGN_FLAG;
125 public Decimal(int val)
133 lo32 = ((uint)~val) + 1;
143 [CLSCompliant(false)]
144 public Decimal(uint val)
147 ss32 = hi32 = mid32 = 0;
150 public Decimal(long val)
158 ulong u = ((ulong)~val) + 1;
160 mid32 = (uint)(u >> 32);
165 ulong u = (ulong)val;
167 mid32 = (uint)(u >> 32);
172 [CLSCompliant(false)]
173 public Decimal(ulong uval)
179 mid32 = (uint)(uval >> 32);
183 public Decimal (float val)
185 if (val > (float)Decimal.MaxValue || val < (float)Decimal.MinValue) {
\r
186 throw new OverflowException (Locale.GetText (
\r
187 "Value is greater than Decimal.MaxValue or less than Decimal.MinValue"));
189 // we must respect the precision (double2decimal doesn't)
190 Decimal d = Decimal.Parse (val.ToString (CultureInfo.InvariantCulture),
191 NumberStyles.Float, CultureInfo.InvariantCulture);
198 public Decimal (double val)
200 if (val > (double)Decimal.MaxValue || val < (double)Decimal.MinValue) {
\r
201 throw new OverflowException (Locale.GetText (
\r
202 "Value is greater than Decimal.MaxValue or less than Decimal.MinValue"));
204 // we must respect the precision (double2decimal doesn't)
205 Decimal d = Decimal.Parse (val.ToString (CultureInfo.InvariantCulture),
206 NumberStyles.Float, CultureInfo.InvariantCulture);
213 public Decimal(int[] bits)
217 throw new ArgumentNullException(Locale.GetText ("Bits is a null reference"));
220 if (bits.GetLength(0) != 4)
222 throw new ArgumentException(Locale.GetText ("bits does not contain four values"));
226 lo32 = (uint) bits[0];
227 mid32 = (uint) bits[1];
228 hi32 = (uint) bits[2];
229 ss32 = (uint) bits[3];
230 byte scale = (byte)(ss32 >> SCALE_SHIFT);
231 if (scale > MAX_SCALE || (ss32 & RESERVED_SS32_BITS) != 0)
233 throw new ArgumentException(Locale.GetText ("Invalid bits[3]"));
238 public static decimal FromOACurrency(long cy)
240 return (decimal)cy / (decimal)10000;
243 public static int[] GetBits(Decimal d)
247 return new int[] { (int)d.lo32, (int)d.mid32, (int)d.hi32,
252 public static Decimal Negate(Decimal d)
259 public static Decimal Add(Decimal d1, Decimal d2)
261 if (decimalIncr(ref d1, ref d2) == 0)
264 throw new OverflowException(Locale.GetText ("Overflow on adding decimal number"));
267 public static Decimal Subtract(Decimal d1, Decimal d2)
269 d2.ss32 ^= SIGN_FLAG;
270 int result = decimalIncr(ref d1, ref d2);
274 throw new OverflowException(Locale.GetText ("Overflow on subtracting decimal numbers ("+result+")"));
277 public override int GetHashCode ()
279 return (int) (ss32 ^ hi32 ^ lo32 ^ mid32);
282 public static Decimal operator +(Decimal d1, Decimal d2)
287 public static Decimal operator --(Decimal d)
289 return Add(d, MinusOne);
292 public static Decimal operator ++(Decimal d)
297 public static Decimal operator -(Decimal d1, Decimal d2)
299 return Subtract(d1, d2);
302 public static Decimal operator -(Decimal d)
307 public static Decimal operator +(Decimal d)
312 public static Decimal operator *(Decimal d1, Decimal d2)
314 return Multiply(d1, d2);
317 public static Decimal operator /(Decimal d1, Decimal d2)
319 return Divide(d1, d2);
322 public static Decimal operator %(Decimal d1, Decimal d2)
324 return Remainder(d1, d2);
327 private static ulong u64 (Decimal value)
331 decimalFloorAndTrunc (ref value, 0);
332 if (decimal2UInt64 (ref value, out result) != 0) {
333 throw new System.OverflowException ();
338 private static long s64 (Decimal value)
342 decimalFloorAndTrunc (ref value, 0);
343 if (decimal2Int64 (ref value, out result) != 0) {
344 throw new System.OverflowException ();
349 public static explicit operator byte (Decimal val)
351 ulong result = u64 (val);
352 return checked ((byte) result);
355 [CLSCompliant (false)]
356 public static explicit operator sbyte (Decimal val)
358 long result = s64 (val);
359 return checked ((sbyte) result);
362 public static explicit operator char (Decimal val)
364 ulong result = u64 (val);
365 return checked ((char) result);
368 public static explicit operator short (Decimal val)
370 long result = s64 (val);
371 return checked ((short) result);
374 [CLSCompliant (false)]
375 public static explicit operator ushort (Decimal val)
377 ulong result = u64 (val);
378 return checked ((ushort) result);
381 public static explicit operator int (Decimal val)
383 long result = s64 (val);
384 return checked ((int) result);
387 [CLSCompliant(false)]
388 public static explicit operator uint (Decimal val)
390 ulong result = u64 (val);
391 return checked ((uint) result);
394 public static explicit operator long (Decimal val)
399 [CLSCompliant(false)]
400 public static explicit operator ulong (Decimal val)
405 public static implicit operator Decimal(byte val)
407 return new Decimal(val);
410 [CLSCompliant(false)]
411 public static implicit operator Decimal(sbyte val)
413 return new Decimal(val);
416 public static implicit operator Decimal(short val)
418 return new Decimal(val);
421 [CLSCompliant(false)]
422 public static implicit operator Decimal(ushort val)
424 return new Decimal(val);
427 public static implicit operator Decimal(char val)
429 return new Decimal(val);
432 public static implicit operator Decimal(int val)
434 return new Decimal(val);
437 [CLSCompliant(false)]
438 public static implicit operator Decimal(uint val)
440 return new Decimal(val);
443 public static implicit operator Decimal(long val)
445 return new Decimal(val);
448 [CLSCompliant(false)]
449 public static implicit operator Decimal(ulong val)
451 return new Decimal(val);
454 public static explicit operator Decimal(float val)
456 return new Decimal(val);
459 public static explicit operator Decimal(double val)
461 return new Decimal(val);
464 public static explicit operator float(Decimal val)
466 return (float) (double) val;
469 public static explicit operator double(Decimal val)
471 return decimal2double(ref val);
475 public static bool operator !=(Decimal d1, Decimal d2)
477 return !Equals(d1, d2);
480 public static bool operator ==(Decimal d1, Decimal d2)
482 return Equals(d1, d2);
485 public static bool operator >(Decimal d1, Decimal d2)
487 return decimalCompare(ref d1, ref d2) > 0;
490 public static bool operator >=(Decimal d1, Decimal d2)
492 return decimalCompare(ref d1, ref d2) >= 0;
495 public static bool operator <(Decimal d1, Decimal d2)
497 return decimalCompare(ref d1, ref d2) < 0;
500 public static bool operator <=(Decimal d1, Decimal d2)
502 return decimalCompare(ref d1, ref d2) <= 0;
505 public static bool Equals(Decimal d1, Decimal d2)
507 return decimalCompare(ref d1, ref d2) == 0;
510 public override bool Equals(object o)
515 return Equals((Decimal) o, this);
518 // avoid unmanaged call
519 private bool IsZero ()
521 return ((hi32 == 0) && (lo32 == 0) && (mid32 == 0));
524 // avoid unmanaged call
525 private bool IsNegative ()
527 return ((ss32 & 0x80000000) == 0x80000000);
530 public static Decimal Floor(Decimal d)
532 decimalFloorAndTrunc(ref d, 1);
536 public static Decimal Truncate(Decimal d)
538 decimalFloorAndTrunc(ref d, 0);
542 public static Decimal Round (Decimal d, int decimals)
544 if (decimals < 0 || decimals > 28) {
545 throw new ArgumentOutOfRangeException ("decimals", "[0,28]");
548 bool negative = d.IsNegative ();
552 // Moved from Math.cs because it's easier to fix the "sign"
553 // issue here :( as the logic is OK only for positive numbers
554 decimal p = (decimal) Math.Pow (10, decimals);
555 decimal int_part = Decimal.Floor (d);
556 decimal dec_part = d - int_part;
557 dec_part *= 10000000000000000000000000000M;
558 dec_part = Decimal.Floor(dec_part);
559 dec_part /= (10000000000000000000000000000M / p);
560 dec_part = Math.Round (dec_part);
562 decimal result = int_part + dec_part;
564 // that fixes the precision/scale (which we must keep for output)
565 // (moved and adapted from System.Data.SqlTypes.SqlMoney)
566 long scaleDiff = decimals - ((result.ss32 & 0x7FFF0000) >> 16);
569 // note: here we always work with positive numbers
570 while (scaleDiff > 0) {
571 if (result > MaxValueDiv10)
577 else if (scaleDiff < 0) {
578 while (scaleDiff < 0) {
583 result.ss32 = (uint)((decimals - scaleDiff) << SCALE_SHIFT);
586 result.ss32 ^= SIGN_FLAG;
590 public static Decimal Multiply (Decimal d1, Decimal d2)
592 if (d1.IsZero () || d2.IsZero ())
595 if (decimalMult (ref d1, ref d2) != 0)
596 throw new OverflowException ();
600 public static Decimal Divide (Decimal d1, Decimal d2)
603 throw new DivideByZeroException ();
609 d1.ss32 ^= SIGN_FLAG;
611 return Decimal.MinusOne;
612 d1.ss32 ^= SIGN_FLAG;
615 if (decimalDiv (out result, ref d1, ref d2) != 0)
616 throw new OverflowException ();
621 public static Decimal Remainder (Decimal d1, Decimal d2)
624 throw new DivideByZeroException ();
628 bool negative = d1.IsNegative ();
630 d1.ss32 ^= SIGN_FLAG;
631 if (d2.IsNegative ())
632 d2.ss32 ^= SIGN_FLAG;
642 if (decimalIntDiv (out result, ref d1, ref d2) != 0)
643 throw new OverflowException ();
645 // FIXME: not really performant here
646 result = d1 - result * d2;
650 result.ss32 ^= SIGN_FLAG;
654 public static int Compare(Decimal d1, Decimal d2)
656 return decimalCompare(ref d1, ref d2);
659 public int CompareTo(object val)
664 if (!(val is Decimal))
665 throw new ArgumentException (Locale.GetText ("Value is not a System.Decimal"));
667 Decimal d2 = (Decimal)val;
668 return decimalCompare(ref this, ref d2);
672 public int CompareTo(Decimal value)
674 return decimalCompare(ref this, ref value);
677 public bool Equals(Decimal value)
679 return Equals(value, this);
683 public static Decimal Parse(string s)
685 return Parse(s, NumberStyles.Number, null);
688 public static Decimal Parse(string s, NumberStyles style)
690 return Parse(s, style, null);
693 public static Decimal Parse(string s, IFormatProvider provider)
695 return Parse(s, NumberStyles.Number, provider);
698 private static string stripStyles(string s, NumberStyles style, NumberFormatInfo nfi,
699 out int decPos, out bool isNegative, out bool expFlag, out int exp)
701 string invalidChar = Locale.GetText ("Invalid character at position ");
702 string invalidExponent = Locale.GetText ("Invalid exponent");
708 bool hasSign = false;
709 bool hasOpeningParentheses = false;
710 bool hasDecimalPoint = false;
711 bool allowedLeadingWhiteSpace = ((style & NumberStyles.AllowLeadingWhite) != 0);
712 bool allowedTrailingWhiteSpace = ((style & NumberStyles.AllowTrailingWhite) != 0);
713 bool allowedLeadingSign = ((style & NumberStyles.AllowLeadingSign) != 0);
714 bool allowedTrailingSign = ((style & NumberStyles.AllowTrailingSign) != 0);
715 bool allowedParentheses = ((style & NumberStyles.AllowParentheses) != 0);
716 bool allowedThousands = ((style & NumberStyles.AllowThousands) != 0);
717 bool allowedDecimalPoint = ((style & NumberStyles.AllowDecimalPoint) != 0);
718 bool allowedExponent = ((style & NumberStyles.AllowExponent) != 0);
720 /* get rid of currency symbol */
721 bool hasCurrency = false;
722 if ((style & NumberStyles.AllowCurrencySymbol) != 0)
724 int index = s.IndexOf(nfi.CurrencySymbol);
727 s = s.Remove(index, nfi.CurrencySymbol.Length);
732 string decimalSep = (hasCurrency) ? nfi.CurrencyDecimalSeparator : nfi.NumberDecimalSeparator;
733 string groupSep = (hasCurrency) ? nfi.CurrencyGroupSeparator : nfi.NumberGroupSeparator;
738 StringBuilder sb = new StringBuilder(len);
744 if (Char.IsDigit(ch))
746 break; // end of leading
748 else if (allowedLeadingWhiteSpace && Char.IsWhiteSpace(ch))
752 else if (allowedParentheses && ch == '(' && !hasSign && !hasOpeningParentheses)
754 hasOpeningParentheses = true;
759 else if (allowedLeadingSign && ch == nfi.NegativeSign[0] && !hasSign)
761 int slen = nfi.NegativeSign.Length;
762 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
769 else if (allowedLeadingSign && ch == nfi.PositiveSign[0] && !hasSign)
771 int slen = nfi.PositiveSign.Length;
772 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
778 else if (allowedDecimalPoint && ch == decimalSep[0])
780 int slen = decimalSep.Length;
781 if (slen != 1 && s.IndexOf(decimalSep, pos, slen) != pos)
783 throw new FormatException(invalidChar + pos);
789 throw new FormatException(invalidChar + pos);
794 throw new FormatException(Locale.GetText ("No digits found"));
800 if (Char.IsDigit(ch))
805 else if (allowedThousands && ch == groupSep[0])
807 int slen = groupSep.Length;
808 if (slen != 1 && s.IndexOf(groupSep, pos, slen) != pos)
810 throw new FormatException(invalidChar + pos);
814 else if (allowedDecimalPoint && ch == decimalSep[0] && !hasDecimalPoint)
816 int slen = decimalSep.Length;
817 if (slen == 1 || s.IndexOf(decimalSep, pos, slen) == pos)
820 hasDecimalPoint = true;
834 if (allowedExponent && Char.ToUpperInvariant (ch) == 'E')
837 pos++; if (pos >= len) throw new FormatException(invalidExponent);
839 bool isNegativeExp = false;
840 if (ch == nfi.PositiveSign[0])
842 int slen = nfi.PositiveSign.Length;
843 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
845 pos += slen; if (pos >= len) throw new FormatException(invalidExponent);
848 else if (ch == nfi.NegativeSign[0])
850 int slen = nfi.NegativeSign.Length;
851 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
853 pos += slen; if (pos >= len) throw new FormatException(invalidExponent);
854 isNegativeExp = true;
858 if (!Char.IsDigit(ch)) throw new FormatException(invalidExponent);
861 while (pos < len && Char.IsDigit(s[pos]))
867 if (isNegativeExp) exp *= -1;
875 if (allowedTrailingWhiteSpace && Char.IsWhiteSpace(ch))
879 else if (allowedParentheses && ch == ')' && hasOpeningParentheses)
881 hasOpeningParentheses = false;
884 else if (allowedTrailingSign && ch == nfi.NegativeSign[0] && !hasSign)
886 int slen = nfi.NegativeSign.Length;
887 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
894 else if (allowedTrailingSign && ch == nfi.PositiveSign[0] && !hasSign)
896 int slen = nfi.PositiveSign.Length;
897 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
905 throw new FormatException(invalidChar + pos);
909 if (hasOpeningParentheses) throw new FormatException (
910 Locale.GetText ("Closing Parentheses not found"));
912 if (!hasDecimalPoint) decPos = sb.Length;
914 return sb.ToString();
917 public static Decimal Parse (string s, NumberStyles style, IFormatProvider provider)
920 throw new ArgumentNullException ("s");
922 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (provider);
925 bool isNegative, expFlag;
926 s = stripStyles(s, style, nfi, out iDecPos, out isNegative, out expFlag, out exp);
929 throw new Exception (Locale.GetText ("Error in System.Decimal.Parse"));
931 // first we remove leading 0
934 while ((i < iDecPos) && (s [i] == '0'))
936 if ((i > 1) && (len > 1)) {
937 s = s.Substring (i, len - i);
941 // first 0. may not be here but is part of the maximum length
942 int max = ((iDecPos == 0) ? 27 : 28);
944 if (len >= max + 1) {
945 // number lower than MaxValue (base-less) can have better precision
946 if (String.Compare (s, 0, "79228162514264337593543950335", 0, max + 1,
947 false, CultureInfo.InvariantCulture) <= 0) {
952 // then we trunc the string
953 if ((len > max) && (iDecPos < len)) {
954 int round = (s [max] - '0');
955 s = s.Substring (0, max);
961 else if (round == 5) {
966 // banker rounding applies :(
967 int previous = (s [max - 1] - '0');
968 addone = ((previous & 0x01) == 0x01);
972 char[] array = s.ToCharArray ();
975 int b = (array [p] - '0');
976 if (array [p] != '9') {
977 array [p] = (char)(b + '1');
984 if ((p == -1) && (array [0] == '0')) {
986 s = "1".PadRight (iDecPos, '0');
989 s = new String (array);
994 // always work in positive (rounding issues)
995 if (string2decimal (out result, s, (uint)iDecPos, 0) != 0)
996 throw new OverflowException ();
999 if (decimalSetExponent (ref result, exp) != 0)
1000 throw new OverflowException ();
1004 result.ss32 ^= SIGN_FLAG;
1008 public TypeCode GetTypeCode ()
1010 return TypeCode.Decimal;
1013 public static byte ToByte (decimal value)
1015 if (value > Byte.MaxValue || value < Byte.MinValue)
\r
1016 throw new OverflowException (Locale.GetText (
\r
1017 "Value is greater than Byte.MaxValue or less than Byte.MinValue"));
\r
1019 // return truncated value
\r
1020 return (byte)(Decimal.Truncate (value));
\r
1023 public static double ToDouble (decimal value)
1025 return Convert.ToDouble (value);
1028 public static short ToInt16 (decimal value)
1030 if (value > Int16.MaxValue || value < Int16.MinValue)
\r
1031 throw new OverflowException (Locale.GetText (
\r
1032 "Value is greater than Int16.MaxValue or less than Int16.MinValue"));
\r
1034 // return truncated value
\r
1035 return (Int16)(Decimal.Truncate (value));
\r
1038 public static int ToInt32 (decimal value)
1040 if (value > Int32.MaxValue || value < Int32.MinValue)
\r
1041 throw new OverflowException (Locale.GetText (
\r
1042 "Value is greater than Int32.MaxValue or less than Int32.MinValue"));
\r
1044 // return truncated value
\r
1045 return (Int32)(Decimal.Truncate (value));
\r
1048 public static long ToInt64 (decimal value)
1050 if (value > Int64.MaxValue || value < Int64.MinValue)
\r
1051 throw new OverflowException (Locale.GetText (
\r
1052 "Value is greater than Int64.MaxValue or less than Int64.MinValue"));
\r
1054 // return truncated value
\r
1055 return (Int64)(Decimal.Truncate (value));
\r
1058 public static long ToOACurrency (decimal value)
1060 return (long) (value * 10000);
1063 [CLSCompliant(false)]
1064 public static sbyte ToSByte (decimal value)
1066 if (value > SByte.MaxValue || value < SByte.MinValue)
\r
1067 throw new OverflowException (Locale.GetText (
\r
1068 "Value is greater than SByte.MaxValue or less than SByte.MinValue"));
\r
1070 // return truncated value
\r
1071 return (SByte)(Decimal.Truncate (value));
\r
1074 public static float ToSingle (decimal value)
1076 return Convert.ToSingle (value);
1079 [CLSCompliant(false)]
1080 public static ushort ToUInt16 (decimal value)
1082 if (value > UInt16.MaxValue || value < UInt16.MinValue)
\r
1083 throw new OverflowException (Locale.GetText (
\r
1084 "Value is greater than UInt16.MaxValue or less than UInt16.MinValue"));
\r
1086 // return truncated value
\r
1087 return (UInt16)(Decimal.Truncate (value));
\r
1090 [CLSCompliant(false)]
1091 public static uint ToUInt32 (decimal value)
1093 if (value > UInt32.MaxValue || value < UInt32.MinValue)
\r
1094 throw new OverflowException (Locale.GetText (
\r
1095 "Value is greater than UInt32.MaxValue or less than UInt32.MinValue"));
\r
1097 // return truncated value
\r
1098 return (UInt32)(Decimal.Truncate (value));
\r
1101 [CLSCompliant(false)]
1102 public static ulong ToUInt64 (decimal value)
1104 if (value > UInt64.MaxValue || value < UInt64.MinValue)
\r
1105 throw new OverflowException (Locale.GetText (
\r
1106 "Value is greater than UInt64.MaxValue or less than UInt64.MinValue"));
\r
1108 // return truncated value
\r
1109 return (UInt64)(Decimal.Truncate (value));
\r
1112 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
1114 return Convert.ToType (this, conversionType, provider);
1117 bool IConvertible.ToBoolean (IFormatProvider provider)
1119 return Convert.ToBoolean (this);
1122 byte IConvertible.ToByte (IFormatProvider provider)
1124 return Convert.ToByte (this);
1127 char IConvertible.ToChar (IFormatProvider provider)
1129 throw new InvalidCastException ();
1132 DateTime IConvertible.ToDateTime (IFormatProvider provider)
1134 throw new InvalidCastException ();
1137 decimal IConvertible.ToDecimal (IFormatProvider provider)
1142 double IConvertible.ToDouble (IFormatProvider provider)
1144 return Convert.ToDouble (this);
1147 short IConvertible.ToInt16 (IFormatProvider provider)
1149 return Convert.ToInt16 (this);
1152 int IConvertible.ToInt32 (IFormatProvider provider)
1154 return Convert.ToInt32 (this);
1157 long IConvertible.ToInt64 (IFormatProvider provider)
1159 return Convert.ToInt64 (this);
1162 sbyte IConvertible.ToSByte (IFormatProvider provider)
1164 return Convert.ToSByte (this);
1167 float IConvertible.ToSingle (IFormatProvider provider)
1169 return Convert.ToSingle (this);
1172 ushort IConvertible.ToUInt16 (IFormatProvider provider)
1174 return Convert.ToUInt16 (this);
1177 uint IConvertible.ToUInt32 (IFormatProvider provider)
1179 return Convert.ToUInt32 (this);
1182 ulong IConvertible.ToUInt64 (IFormatProvider provider)
1184 return Convert.ToUInt64 (this);
1187 public string ToString (string format, IFormatProvider provider)
1189 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (provider);
1191 // use "G" for null or empty string
1192 if ((format == null) || (format.Length == 0))
1195 return DecimalFormatter.NumberToString (format, nfi, this);
1198 public override string ToString()
1200 return ToString("G", null);
1203 public string ToString(string format)
1205 return ToString(format, null);
1208 public string ToString(IFormatProvider provider)
1210 return ToString("G", provider);
1214 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1215 private static extern int decimal2UInt64(ref Decimal val,
1218 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1219 private static extern int decimal2Int64(ref Decimal val,
1222 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1223 private static extern int double2decimal(out Decimal erg,
1224 double val, int digits);
1226 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1227 private static extern int decimalIncr(ref Decimal d1, ref Decimal d2);
1229 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1230 internal static extern int decimal2string(ref Decimal val,
1231 int digits, int decimals, char[] bufDigits, int bufSize, out int decPos, out int sign);
1233 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1234 internal static extern int string2decimal(out Decimal val, String sDigits, uint decPos, int sign);
1236 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1237 internal static extern int decimalSetExponent(ref Decimal val, int exp);
1239 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1240 private static extern double decimal2double(ref Decimal val);
1242 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1243 private static extern void decimalFloorAndTrunc(ref Decimal val,
1246 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1247 private static extern void decimalRound(ref Decimal val, int decimals);
1249 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1250 private static extern int decimalMult(ref Decimal pd1, ref Decimal pd2);
1252 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1253 private static extern int decimalDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1256 private static extern int decimalIntDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1258 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1259 private static extern int decimalCompare(ref Decimal d1, ref Decimal d2);
1261 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1262 [DllImport("libdec", EntryPoint="decimal2UInt64")]
1263 private static extern int decimal2UInt64(ref Decimal val,
1266 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1267 [DllImport("libdec", EntryPoint="decimal2Int64")]
1268 private static extern int decimal2Int64(ref Decimal val,
1271 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1272 [DllImport("libdec", EntryPoint="double2decimal")]
1273 private static extern int double2decimal(out Decimal erg,
1274 double val, int digits);
1276 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1277 [DllImport("libdec", EntryPoint="decimalIncr")]
1278 private static extern int decimalIncr(ref Decimal d1, ref Decimal d2);
1280 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1281 [DllImport("libdec", EntryPoint="decimal2string")]
1282 internal static extern int decimal2string(ref Decimal val,
1283 int digits, int decimals,
1284 [MarshalAs(UnmanagedType.LPWStr)]StringBuilder bufDigits,
1285 int bufSize, out int decPos, out int sign);
1287 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1288 [DllImport("libdec", EntryPoint="string2decimal")]
1289 internal static extern int string2decimal(out Decimal val,
1290 [MarshalAs(UnmanagedType.LPWStr)]String sDigits,
1291 uint decPos, int sign);
1293 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1294 [DllImport("libdec", EntryPoint="decimalSetExponent")]
1295 internal static extern int decimalSetExponent(ref Decimal val, int exp);
1297 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1298 [DllImport("libdec", EntryPoint="decimal2double")]
1299 private static extern double decimal2double(ref Decimal val);
1301 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1302 [DllImport("libdec", EntryPoint="decimalFloorAndTrunc")]
1303 private static extern void decimalFloorAndTrunc(ref Decimal val,
1306 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1307 [DllImport("libdec", EntryPoint="decimalRound")]
1308 private static extern void decimalRound(ref Decimal val, int decimals);
1310 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1311 [DllImport("libdec", EntryPoint="decimalMult")]
1312 private static extern int decimalMult(ref Decimal pd1, ref Decimal pd2);
1314 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1315 [DllImport("libdec", EntryPoint="decimalDiv")]
1316 private static extern int decimalDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1318 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1319 [DllImport("libdec", EntryPoint="decimalIntDiv")]
1320 private static extern int decimalIntDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1322 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1323 [DllImport("libdec", EntryPoint="decimalCompare")]
1324 private static extern int decimalCompare(ref Decimal d1, ref Decimal d2);