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;
40 using System.Runtime.ConstrainedExecution;
41 using System.Runtime.Serialization;
44 using System.Runtime.InteropServices;
51 /// Represents a floating-point decimal data type with up to 29 significant
52 /// digits, suitable for financial and commercial calculations
55 [System.Runtime.InteropServices.ComVisible (true)]
56 public struct Decimal: IFormattable, IConvertible, IComparable, IComparable<Decimal>, IEquatable <Decimal>
58 , IDeserializationCallback
61 public const decimal MinValue = -79228162514264337593543950335m;
62 public const decimal MaxValue = 79228162514264337593543950335m;
64 public const decimal MinusOne = -1;
65 public const decimal One = 1;
66 public const decimal Zero = 0;
68 private static readonly Decimal MaxValueDiv10 = MaxValue / 10;
71 private const uint MAX_SCALE = 28;
72 private const uint SIGN_FLAG = 0x80000000;
73 private const int SCALE_SHIFT = 16;
74 private const uint RESERVED_SS32_BITS = 0x7F00FFFF;
76 // internal representation of decimal
82 public Decimal (int lo, int mid, int hi, bool isNegative, byte scale)
87 this.mid = (uint) mid;
90 if (scale > MAX_SCALE)
91 throw new ArgumentOutOfRangeException (Locale.GetText ("scale must be between 0 and 28"));
94 flags <<= SCALE_SHIFT;
95 if (isNegative) flags |= SIGN_FLAG;
99 public Decimal (int value)
107 lo = ((uint)~value) + 1;
117 [CLSCompliant(false)]
118 public Decimal (uint value)
121 flags = hi = mid = 0;
124 public Decimal (long value)
132 ulong u = ((ulong)~value) + 1;
134 mid = (uint)(u >> 32);
139 ulong u = (ulong)value;
141 mid = (uint)(u >> 32);
146 [CLSCompliant(false)]
147 public Decimal (ulong value)
153 mid = (uint)(value >> 32);
157 public Decimal (float value)
161 // We cant use the double2decimal method
162 // because it incorrectly turns the floating point
163 // value 1.23456789E-25F which should be:
164 // 0.0000000000000000000000001235
165 // into the incorrect:
166 // 0.0000000000000000000000001234
168 // The code currently parses the double value 0.6 as
171 // And we have a patch for that called (trim
172 if (double2decimal (out this, value, 7) != 0)
173 throw new OverflowException ();
175 if (value > (float)Decimal.MaxValue || value < (float)Decimal.MinValue ||
176 float.IsNaN (value) || float.IsNegativeInfinity (value) || float.IsPositiveInfinity (value)) {
177 throw new OverflowException (Locale.GetText (
178 "Value {0} is greater than Decimal.MaxValue or less than Decimal.MinValue", value));
181 // we must respect the precision (double2decimal doesn't)
182 Decimal d = Decimal.Parse (value.ToString (CultureInfo.InvariantCulture),
183 NumberStyles.Float, CultureInfo.InvariantCulture);
191 public Decimal (double value)
195 // We cant use the double2decimal method
196 // because it incorrectly turns the floating point
197 // value 1.23456789E-25F which should be:
198 // 0.0000000000000000000000001235
199 // into the incorrect:
200 // 0.0000000000000000000000001234
202 // The code currently parses the double value 0.6 as
205 // And we have a patch for that called (trim
206 if (double2decimal (out this, value, 15) != 0)
207 throw new OverflowException ();
209 if (value > (double)Decimal.MaxValue || value < (double)Decimal.MinValue ||
210 double.IsNaN (value) || double.IsNegativeInfinity (value) || double.IsPositiveInfinity (value)) {
211 throw new OverflowException (Locale.GetText (
212 "Value {0} is greater than Decimal.MaxValue or less than Decimal.MinValue", value));
214 // we must respect the precision (double2decimal doesn't)
215 Decimal d = Decimal.Parse (value.ToString (CultureInfo.InvariantCulture),
216 NumberStyles.Float, CultureInfo.InvariantCulture);
224 public Decimal (int[] bits)
228 throw new ArgumentNullException (Locale.GetText ("Bits is a null reference"));
231 if (bits.GetLength(0) != 4)
233 throw new ArgumentException (Locale.GetText ("bits does not contain four values"));
238 mid = (uint) bits[1];
240 flags = (uint) bits[3];
241 byte scale = (byte)(flags >> SCALE_SHIFT);
242 if (scale > MAX_SCALE || (flags & RESERVED_SS32_BITS) != 0)
244 throw new ArgumentException (Locale.GetText ("Invalid bits[3]"));
249 public static decimal FromOACurrency (long cy)
251 return (decimal)cy / (decimal)10000;
254 public static int[] GetBits (Decimal d)
258 return new int[] { (int)d.lo, (int)d.mid, (int)d.hi, (int)d.flags };
262 public static Decimal Negate (Decimal d)
264 d.flags ^= SIGN_FLAG;
268 public static Decimal Add (Decimal d1, Decimal d2)
270 if (decimalIncr (ref d1, ref d2) == 0)
273 throw new OverflowException (Locale.GetText ("Overflow on adding decimal number"));
276 public static Decimal Subtract (Decimal d1, Decimal d2)
278 d2.flags ^= SIGN_FLAG;
279 int result = decimalIncr (ref d1, ref d2);
283 throw new OverflowException (Locale.GetText ("Overflow on subtracting decimal numbers ("+result+")"));
286 public override int GetHashCode ()
288 return (int) (flags ^ hi ^ lo ^ mid);
291 public static Decimal operator + (Decimal d1, Decimal d2)
296 public static Decimal operator -- (Decimal d)
298 return Add(d, MinusOne);
301 public static Decimal operator ++ (Decimal d)
306 public static Decimal operator - (Decimal d1, Decimal d2)
308 return Subtract (d1, d2);
311 public static Decimal operator - (Decimal d)
316 public static Decimal operator + (Decimal d)
321 public static Decimal operator * (Decimal d1, Decimal d2)
323 return Multiply (d1, d2);
326 public static Decimal operator / (Decimal d1, Decimal d2)
328 return Divide (d1, d2);
331 public static Decimal operator % (Decimal d1, Decimal d2)
333 return Remainder (d1, d2);
336 private static ulong u64 (Decimal value)
340 decimalFloorAndTrunc (ref value, 0);
341 if (decimal2UInt64 (ref value, out result) != 0) {
342 throw new System.OverflowException ();
347 private static long s64 (Decimal value)
351 decimalFloorAndTrunc (ref value, 0);
352 if (decimal2Int64 (ref value, out result) != 0) {
353 throw new System.OverflowException ();
358 public static explicit operator byte (Decimal value)
360 ulong result = u64 (value);
361 return checked ((byte) result);
364 [CLSCompliant (false)]
365 public static explicit operator sbyte (Decimal value)
367 long result = s64 (value);
368 return checked ((sbyte) result);
371 public static explicit operator char (Decimal value)
373 ulong result = u64 (value);
374 return checked ((char) result);
377 public static explicit operator short (Decimal value)
379 long result = s64 (value);
380 return checked ((short) result);
383 [CLSCompliant (false)]
384 public static explicit operator ushort (Decimal value)
386 ulong result = u64 (value);
387 return checked ((ushort) result);
390 public static explicit operator int (Decimal value)
392 long result = s64 (value);
393 return checked ((int) result);
396 [CLSCompliant(false)]
397 public static explicit operator uint (Decimal value)
399 ulong result = u64 (value);
400 return checked ((uint) result);
403 public static explicit operator long (Decimal value)
408 [CLSCompliant(false)]
409 public static explicit operator ulong (Decimal value)
414 public static implicit operator Decimal (byte value)
416 return new Decimal (value);
419 [CLSCompliant(false)]
420 public static implicit operator Decimal (sbyte value)
422 return new Decimal (value);
425 public static implicit operator Decimal (short value)
427 return new Decimal (value);
430 [CLSCompliant(false)]
431 public static implicit operator Decimal (ushort value)
433 return new Decimal (value);
436 public static implicit operator Decimal (char value)
438 return new Decimal (value);
441 public static implicit operator Decimal (int value)
443 return new Decimal (value);
446 [CLSCompliant(false)]
447 public static implicit operator Decimal (uint value)
449 return new Decimal (value);
452 public static implicit operator Decimal (long value)
454 return new Decimal (value);
457 [CLSCompliant(false)]
458 public static implicit operator Decimal (ulong value)
460 return new Decimal (value);
463 public static explicit operator Decimal (float value)
465 return new Decimal (value);
468 public static explicit operator Decimal (double value)
470 return new Decimal (value);
473 public static explicit operator float (Decimal value)
475 return (float) (double) value;
478 public static explicit operator double (Decimal value)
480 return decimal2double (ref value);
484 public static bool operator != (Decimal d1, Decimal d2)
486 return !Equals (d1, d2);
489 public static bool operator == (Decimal d1, Decimal d2)
491 return Equals (d1, d2);
494 public static bool operator > (Decimal d1, Decimal d2)
496 return Compare (d1, d2) > 0;
499 public static bool operator >= (Decimal d1, Decimal d2)
501 return Compare (d1, d2) >= 0;
504 public static bool operator < (Decimal d1, Decimal d2)
506 return Compare (d1, d2) < 0;
509 public static bool operator <= (Decimal d1, Decimal d2)
511 return Compare (d1, d2) <= 0;
514 public static bool Equals (Decimal d1, Decimal d2)
516 return Compare (d1, d2) == 0;
519 public override bool Equals (object value)
521 if (!(value is Decimal))
524 return Equals ((Decimal) value, this);
527 // avoid unmanaged call
528 private bool IsZero ()
530 return ((hi == 0) && (lo == 0) && (mid == 0));
533 // avoid unmanaged call
534 private bool IsNegative ()
536 return ((flags & 0x80000000) == 0x80000000);
539 public static Decimal Floor (Decimal d)
541 decimalFloorAndTrunc (ref d, 1);
545 public static Decimal Truncate (Decimal d)
547 decimalFloorAndTrunc (ref d, 0);
551 public static Decimal Round (Decimal d, int decimals)
553 return Round (d, decimals, MidpointRounding.ToEven);
556 public static Decimal Round (Decimal d, int decimals, MidpointRounding mode)
558 if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
559 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
561 if (decimals < 0 || decimals > 28) {
562 throw new ArgumentOutOfRangeException ("decimals", "[0,28]");
565 bool negative = d.IsNegative ();
567 d.flags ^= SIGN_FLAG;
569 // Moved from Math.cs because it's easier to fix the "sign"
570 // issue here :( as the logic is OK only for positive numbers
571 decimal p = (decimal) Math.Pow (10, decimals);
572 decimal int_part = Decimal.Floor (d);
573 decimal dec_part = d - int_part;
574 dec_part *= 10000000000000000000000000000M;
575 dec_part = Decimal.Floor(dec_part);
576 dec_part /= (10000000000000000000000000000M / p);
577 dec_part = Math.Round (dec_part, mode);
579 decimal result = int_part + dec_part;
581 // that fixes the precision/scale (which we must keep for output)
582 // (moved and adapted from System.Data.SqlTypes.SqlMoney)
583 long scaleDiff = decimals - ((result.flags & 0x7FFF0000) >> 16);
586 // note: here we always work with positive numbers
587 while (scaleDiff > 0) {
588 if (result > MaxValueDiv10)
594 else if (scaleDiff < 0) {
595 while (scaleDiff < 0) {
600 result.flags = (uint)((decimals - scaleDiff) << SCALE_SHIFT);
603 result.flags ^= SIGN_FLAG;
607 public static Decimal Round (Decimal d)
609 return Math.Round (d);
612 public static Decimal Round (Decimal d, MidpointRounding mode)
614 return Math.Round (d, mode);
617 public static Decimal Multiply (Decimal d1, Decimal d2)
619 if (d1.IsZero () || d2.IsZero ())
622 if (decimalMult (ref d1, ref d2) != 0)
623 throw new OverflowException ();
627 public static Decimal Divide (Decimal d1, Decimal d2)
630 throw new DivideByZeroException ();
634 d1.flags ^= SIGN_FLAG;
635 d1.flags ^= SIGN_FLAG;
638 if (decimalDiv (out result, ref d1, ref d2) != 0)
639 throw new OverflowException ();
644 public static Decimal Remainder (Decimal d1, Decimal d2)
647 throw new DivideByZeroException ();
651 bool negative = d1.IsNegative ();
653 d1.flags ^= SIGN_FLAG;
654 if (d2.IsNegative ())
655 d2.flags ^= SIGN_FLAG;
665 if (decimalDiv (out result, ref d1, ref d2) != 0)
666 throw new OverflowException ();
667 result = Decimal.Truncate (result);
669 // FIXME: not really performant here
670 result = d1 - result * d2;
674 result.flags ^= SIGN_FLAG;
678 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
679 public static int Compare (Decimal d1, Decimal d2)
681 return decimalCompare (ref d1, ref d2);
684 public int CompareTo (object value)
689 if (!(value is Decimal))
690 throw new ArgumentException (Locale.GetText ("Value is not a System.Decimal"));
692 return Compare (this, (Decimal)value);
695 public int CompareTo (Decimal value)
697 return Compare (this, value);
700 public bool Equals (Decimal value)
702 return Equals (value, this);
705 public static Decimal Ceiling (Decimal d)
707 return Math.Ceiling (d);
710 public static Decimal Parse (string s)
712 return Parse (s, NumberStyles.Number, null);
715 public static Decimal Parse (string s, NumberStyles style)
717 return Parse (s, style, null);
720 public static Decimal Parse (string s, IFormatProvider provider)
722 return Parse (s, NumberStyles.Number, provider);
725 static void ThrowAtPos (int pos)
727 throw new FormatException (String.Format (Locale.GetText ("Invalid character at position {0}"), pos));
730 static void ThrowInvalidExp ()
732 throw new FormatException (Locale.GetText ("Invalid exponent"));
735 private static string stripStyles (string s, NumberStyles style, NumberFormatInfo nfi,
736 out int decPos, out bool isNegative, out bool expFlag, out int exp, bool throwex)
743 bool hasSign = false;
744 bool hasOpeningParentheses = false;
745 bool hasDecimalPoint = false;
746 bool allowedLeadingWhiteSpace = ((style & NumberStyles.AllowLeadingWhite) != 0);
747 bool allowedTrailingWhiteSpace = ((style & NumberStyles.AllowTrailingWhite) != 0);
748 bool allowedLeadingSign = ((style & NumberStyles.AllowLeadingSign) != 0);
749 bool allowedTrailingSign = ((style & NumberStyles.AllowTrailingSign) != 0);
750 bool allowedParentheses = ((style & NumberStyles.AllowParentheses) != 0);
751 bool allowedThousands = ((style & NumberStyles.AllowThousands) != 0);
752 bool allowedDecimalPoint = ((style & NumberStyles.AllowDecimalPoint) != 0);
753 bool allowedExponent = ((style & NumberStyles.AllowExponent) != 0);
755 /* get rid of currency symbol */
756 bool hasCurrency = false;
757 if ((style & NumberStyles.AllowCurrencySymbol) != 0)
759 int index = s.IndexOf (nfi.CurrencySymbol);
762 s = s.Remove (index, nfi.CurrencySymbol.Length);
767 string decimalSep = (hasCurrency) ? nfi.CurrencyDecimalSeparator : nfi.NumberDecimalSeparator;
768 string groupSep = (hasCurrency) ? nfi.CurrencyGroupSeparator : nfi.NumberGroupSeparator;
773 StringBuilder sb = new StringBuilder (len);
779 if (Char.IsDigit (ch))
781 break; // end of leading
783 else if (allowedLeadingWhiteSpace && Char.IsWhiteSpace (ch))
787 else if (allowedParentheses && ch == '(' && !hasSign && !hasOpeningParentheses)
789 hasOpeningParentheses = true;
794 else if (allowedLeadingSign && ch == nfi.NegativeSign[0] && !hasSign)
796 int slen = nfi.NegativeSign.Length;
797 if (slen == 1 || s.IndexOf (nfi.NegativeSign, pos, slen) == pos)
804 else if (allowedLeadingSign && ch == nfi.PositiveSign[0] && !hasSign)
806 int slen = nfi.PositiveSign.Length;
807 if (slen == 1 || s.IndexOf (nfi.PositiveSign, pos, slen) == pos)
813 else if (allowedDecimalPoint && ch == decimalSep[0])
815 int slen = decimalSep.Length;
816 if (slen != 1 && s.IndexOf (decimalSep, pos, slen) != pos)
836 throw new FormatException (Locale.GetText ("No digits found"));
845 if (Char.IsDigit (ch))
850 else if (allowedThousands && ch == groupSep[0] && ch != decimalSep [0])
852 int slen = groupSep.Length;
853 if (slen != 1 && s.IndexOf(groupSep, pos, slen) != pos)
862 else if (allowedDecimalPoint && ch == decimalSep[0] && !hasDecimalPoint)
864 int slen = decimalSep.Length;
865 if (slen == 1 || s.IndexOf(decimalSep, pos, slen) == pos)
868 hasDecimalPoint = true;
882 if (allowedExponent && Char.ToUpperInvariant (ch) == 'E')
893 bool isNegativeExp = false;
894 if (ch == nfi.PositiveSign[0])
896 int slen = nfi.PositiveSign.Length;
897 if (slen == 1 || s.IndexOf (nfi.PositiveSign, pos, slen) == pos)
908 else if (ch == nfi.NegativeSign[0])
910 int slen = nfi.NegativeSign.Length;
911 if (slen == 1 || s.IndexOf (nfi.NegativeSign, pos, slen) == pos)
920 isNegativeExp = true;
924 if (!Char.IsDigit(ch)) {
933 while (pos < len && Char.IsDigit (s[pos]))
939 if (isNegativeExp) exp *= -1;
947 if (allowedTrailingWhiteSpace && Char.IsWhiteSpace (ch))
951 else if (allowedParentheses && ch == ')' && hasOpeningParentheses)
953 hasOpeningParentheses = false;
956 else if (allowedTrailingSign && ch == nfi.NegativeSign[0] && !hasSign)
958 int slen = nfi.NegativeSign.Length;
959 if (slen == 1 || s.IndexOf (nfi.NegativeSign, pos, slen) == pos)
966 else if (allowedTrailingSign && ch == nfi.PositiveSign[0] && !hasSign)
968 int slen = nfi.PositiveSign.Length;
969 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
977 // trailing zero characters are allowed
979 while (++pos < len && s [pos] == 0)
992 if (hasOpeningParentheses) {
994 throw new FormatException (Locale.GetText ("Closing Parentheses not found"));
999 if (!hasDecimalPoint)
1002 return sb.ToString ();
1005 public static Decimal Parse (string s, NumberStyles style, IFormatProvider provider)
1008 throw new ArgumentNullException ("s");
1010 if ((style & NumberStyles.AllowHexSpecifier) != 0)
1011 throw new ArgumentException ("Decimal.TryParse does not accept AllowHexSpecifier", "style");
1014 PerformParse (s, style, provider, out result, true);
1018 public static bool TryParse (string s, out Decimal result)
1024 return PerformParse (s, NumberStyles.Number, null, out result, false);
1027 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out decimal result)
1029 if (s == null || (style & NumberStyles.AllowHexSpecifier) != 0){
1034 return PerformParse (s, style, provider, out result, false);
1037 static bool PerformParse (string s, NumberStyles style, IFormatProvider provider, out Decimal res, bool throwex)
1039 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (provider);
1042 bool isNegative, expFlag;
1043 s = stripStyles(s, style, nfi, out iDecPos, out isNegative, out expFlag, out exp, throwex);
1051 throw new Exception (Locale.GetText ("Error in System.Decimal.Parse"));
1056 // first we remove leading 0
1059 while ((i < iDecPos) && (s [i] == '0'))
1061 if ((i > 1) && (len > 1)) {
1062 s = s.Substring (i, len - i);
1066 // first 0. may not be here but is part of the maximum length
1067 int max = ((iDecPos == 0) ? 27 : 28);
1069 if (len >= max + 1) {
1070 // number lower than MaxValue (base-less) can have better precision
1071 if (String.Compare (s, 0, "79228162514264337593543950335", 0, max + 1,
1072 false, CultureInfo.InvariantCulture) <= 0) {
1077 // then we trunc the string
1078 if ((len > max) && (iDecPos < len)) {
1079 int round = (s [max] - '0');
1080 s = s.Substring (0, max);
1082 bool addone = false;
1086 else if (round == 5) {
1091 // banker rounding applies :(
1092 int previous = (s [max - 1] - '0');
1093 addone = ((previous & 0x01) == 0x01);
1097 char[] array = s.ToCharArray ();
1100 int b = (array [p] - '0');
1101 if (array [p] != '9') {
1102 array [p] = (char)(b + '1');
1109 if ((p == -1) && (array [0] == '0')) {
1111 s = "1".PadRight (iDecPos, '0');
1114 s = new String (array);
1119 // always work in positive (rounding issues)
1120 if (string2decimal (out result, s, (uint)iDecPos, 0) != 0){
1122 throw new OverflowException ();
1128 if (decimalSetExponent (ref result, exp) != 0){
1130 throw new OverflowException ();
1137 result.flags ^= SIGN_FLAG;
1143 public TypeCode GetTypeCode ()
1145 return TypeCode.Decimal;
1148 public static byte ToByte (decimal value)
1150 if (value > Byte.MaxValue || value < Byte.MinValue)
1151 throw new OverflowException (Locale.GetText (
1152 "Value is greater than Byte.MaxValue or less than Byte.MinValue"));
1154 // return truncated value
1155 return (byte)(Decimal.Truncate (value));
1158 public static double ToDouble (decimal d)
1160 return Convert.ToDouble (d);
1163 public static short ToInt16 (decimal value)
1165 if (value > Int16.MaxValue || value < Int16.MinValue)
1166 throw new OverflowException (Locale.GetText (
1167 "Value is greater than Int16.MaxValue or less than Int16.MinValue"));
1169 // return truncated value
1170 return (Int16)(Decimal.Truncate (value));
1173 public static int ToInt32 (decimal d)
1175 if (d > Int32.MaxValue || d < Int32.MinValue)
1176 throw new OverflowException (Locale.GetText (
1177 "Value is greater than Int32.MaxValue or less than Int32.MinValue"));
1179 // return truncated value
1180 return (Int32)(Decimal.Truncate (d));
1183 public static long ToInt64 (decimal d)
1185 if (d > Int64.MaxValue || d < Int64.MinValue)
1186 throw new OverflowException (Locale.GetText (
1187 "Value is greater than Int64.MaxValue or less than Int64.MinValue"));
1189 // return truncated value
1190 return (Int64)(Decimal.Truncate (d));
1193 public static long ToOACurrency (decimal value)
1195 return (long) (value * 10000);
1198 [CLSCompliant(false)]
1199 public static sbyte ToSByte (decimal value)
1201 if (value > SByte.MaxValue || value < SByte.MinValue)
1202 throw new OverflowException (Locale.GetText (
1203 "Value is greater than SByte.MaxValue or less than SByte.MinValue"));
1205 // return truncated value
1206 return (SByte)(Decimal.Truncate (value));
1209 public static float ToSingle (decimal d)
1211 return Convert.ToSingle (d);
1214 [CLSCompliant(false)]
1215 public static ushort ToUInt16 (decimal value)
1217 if (value > UInt16.MaxValue || value < UInt16.MinValue)
1218 throw new OverflowException (Locale.GetText (
1219 "Value is greater than UInt16.MaxValue or less than UInt16.MinValue"));
1221 // return truncated value
1222 return (UInt16)(Decimal.Truncate (value));
1225 [CLSCompliant(false)]
1226 public static uint ToUInt32 (decimal d)
1228 if (d > UInt32.MaxValue || d < UInt32.MinValue)
1229 throw new OverflowException (Locale.GetText (
1230 "Value is greater than UInt32.MaxValue or less than UInt32.MinValue"));
1232 // return truncated value
1233 return (UInt32)(Decimal.Truncate (d));
1236 [CLSCompliant(false)]
1237 public static ulong ToUInt64 (decimal d)
1239 if (d > UInt64.MaxValue || d < UInt64.MinValue)
1240 throw new OverflowException (Locale.GetText (
1241 "Value is greater than UInt64.MaxValue or less than UInt64.MinValue"));
1243 // return truncated value
1244 return (UInt64)(Decimal.Truncate (d));
1247 object IConvertible.ToType (Type targetType, IFormatProvider provider)
1249 if (targetType == null)
1250 throw new ArgumentNullException ("targetType");
1251 return Convert.ToType (this, targetType, provider, false);
1254 bool IConvertible.ToBoolean (IFormatProvider provider)
1256 return Convert.ToBoolean (this);
1259 byte IConvertible.ToByte (IFormatProvider provider)
1261 return Convert.ToByte (this);
1264 char IConvertible.ToChar (IFormatProvider provider)
1266 throw new InvalidCastException ();
1269 DateTime IConvertible.ToDateTime (IFormatProvider provider)
1271 throw new InvalidCastException ();
1274 decimal IConvertible.ToDecimal (IFormatProvider provider)
1279 double IConvertible.ToDouble (IFormatProvider provider)
1281 return Convert.ToDouble (this);
1284 short IConvertible.ToInt16 (IFormatProvider provider)
1286 return Convert.ToInt16 (this);
1289 int IConvertible.ToInt32 (IFormatProvider provider)
1291 return Convert.ToInt32 (this);
1294 long IConvertible.ToInt64 (IFormatProvider provider)
1296 return Convert.ToInt64 (this);
1299 sbyte IConvertible.ToSByte (IFormatProvider provider)
1301 return Convert.ToSByte (this);
1304 float IConvertible.ToSingle (IFormatProvider provider)
1306 return Convert.ToSingle (this);
1309 ushort IConvertible.ToUInt16 (IFormatProvider provider)
1311 return Convert.ToUInt16 (this);
1314 uint IConvertible.ToUInt32 (IFormatProvider provider)
1316 return Convert.ToUInt32 (this);
1319 ulong IConvertible.ToUInt64 (IFormatProvider provider)
1321 return Convert.ToUInt64 (this);
1324 public string ToString (string format, IFormatProvider provider)
1326 return NumberFormatter.NumberToString (format, this, provider);
1329 public override string ToString ()
1331 return ToString ("G", null);
1334 public string ToString (string format)
1336 return ToString (format, null);
1339 public string ToString (IFormatProvider provider)
1341 return ToString ("G", provider);
1345 void IDeserializationCallback.OnDeserialization(object sender)
1351 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1352 private static extern int decimal2UInt64 (ref Decimal val, out ulong result);
1354 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1355 private static extern int decimal2Int64 (ref Decimal val, out long result);
1357 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1358 private static extern int double2decimal (out Decimal erg, double val, int digits);
1360 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1361 private static extern int decimalIncr (ref Decimal d1, ref Decimal d2);
1363 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1364 internal static extern int decimal2string (ref Decimal val,
1365 int digits, int decimals, char[] bufDigits, int bufSize, out int decPos, out int sign);
1367 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1368 internal static extern int string2decimal (out Decimal val, String sDigits, uint decPos, int sign);
1370 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1371 internal static extern int decimalSetExponent (ref Decimal val, int exp);
1373 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1374 private static extern double decimal2double (ref Decimal val);
1376 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1377 private static extern void decimalFloorAndTrunc (ref Decimal val, int floorFlag);
1379 // [MethodImplAttribute(MethodImplOptions.InternalCall)]
1380 // private static extern void decimalRound (ref Decimal val, int decimals);
1382 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1383 private static extern int decimalMult (ref Decimal pd1, ref Decimal pd2);
1385 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1386 private static extern int decimalDiv (out Decimal pc, ref Decimal pa, ref Decimal pb);
1388 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1389 private static extern int decimalIntDiv (out Decimal pc, ref Decimal pa, ref Decimal pb);
1391 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1392 private static extern int decimalCompare (ref Decimal d1, ref Decimal d2);
1394 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1395 [DllImport("libdec", EntryPoint="decimal2UInt64")]
1396 private static extern int decimal2UInt64 (ref Decimal val, out ulong result);
1398 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1399 [DllImport("libdec", EntryPoint="decimal2Int64")]
1400 private static extern int decimal2Int64 (ref Decimal val, out long result);
1402 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1403 [DllImport("libdec", EntryPoint="double2decimal")]
1404 private static extern int double2decimal (out Decimal erg, double val, int digits);
1406 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1407 [DllImport("libdec", EntryPoint="decimalIncr")]
1408 private static extern int decimalIncr (ref Decimal d1, ref Decimal d2);
1410 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1411 [DllImport("libdec", EntryPoint="decimal2string")]
1412 internal static extern int decimal2string (ref Decimal val,
1413 int digits, int decimals,
1414 [MarshalAs(UnmanagedType.LPWStr)]StringBuilder bufDigits,
1415 int bufSize, out int decPos, out int sign);
1417 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1418 [DllImport("libdec", EntryPoint="string2decimal")]
1419 internal static extern int string2decimal (out Decimal val,
1420 [MarshalAs(UnmanagedType.LPWStr)]String sDigits,
1421 uint decPos, int sign);
1423 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1424 [DllImport("libdec", EntryPoint="decimalSetExponent")]
1425 internal static extern int decimalSetExponent (ref Decimal val, int exp);
1427 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1428 [DllImport("libdec", EntryPoint="decimal2double")]
1429 private static extern double decimal2double (ref Decimal val);
1431 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1432 [DllImport("libdec", EntryPoint="decimalFloorAndTrunc")]
1433 private static extern void decimalFloorAndTrunc (ref Decimal val, int floorFlag);
1435 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1436 [DllImport("libdec", EntryPoint="decimalRound")]
1437 private static extern void decimalRound (ref Decimal val, int decimals);
1439 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1440 [DllImport("libdec", EntryPoint="decimalMult")]
1441 private static extern int decimalMult (ref Decimal pd1, ref Decimal pd2);
1443 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1444 [DllImport("libdec", EntryPoint="decimalDiv")]
1445 private static extern int decimalDiv (out Decimal pc, ref Decimal pa, ref Decimal pb);
1447 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1448 [DllImport("libdec", EntryPoint="decimalIntDiv")]
1449 private static extern int decimalIntDiv (out Decimal pc, ref Decimal pa, ref Decimal pb);
1451 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1452 [DllImport("libdec", EntryPoint="decimalCompare")]
1453 private static extern int decimalCompare (ref Decimal d1, ref Decimal d2);