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;
45 using System.Runtime.ConstrainedExecution;
51 /// Represents a floating-point decimal data type with up to 29 significant
52 /// digits, suitable for financial and commercial calculations
56 [System.Runtime.InteropServices.ComVisible (true)]
58 public struct Decimal: IFormattable, IConvertible, IComparable
60 , IComparable<Decimal>, IEquatable <Decimal>
63 #if BOOTSTRAP_WITH_OLDLIB
65 // LAMESPEC: the attributes aren't mentioned, but show up in CorCompare
66 // Unfortunately, corcompare starts throwing security exceptions when
67 // these attributes are present...
69 [DecimalConstantAttribute(0, 1, unchecked((uint)-1), unchecked((uint)-1), unchecked((uint)-1))]
70 public static readonly Decimal MinValue = new Decimal(-1, -1, -1, true, 0);
71 [DecimalConstantAttribute(0, 0, unchecked((uint)-1), unchecked((uint)-1), unchecked((uint)-1))]
72 public static readonly Decimal MaxValue = new Decimal(-1, -1, -1, false, 0);
73 [DecimalConstantAttribute(0, 1, 0, 0, 1)]
74 public static readonly Decimal MinusOne = new Decimal(1, 0, 0, true, 0);
75 [DecimalConstantAttribute(0, 0, 0, 0, 1)]
76 public static readonly Decimal One = new Decimal(1, 0, 0, false, 0);
77 [DecimalConstantAttribute(0, 0, 0, 0, 0)]
78 public static readonly Decimal Zero = new Decimal(0, 0, 0, false, 0);
80 public const decimal MinValue = -79228162514264337593543950335m;
81 public const decimal MaxValue = 79228162514264337593543950335m;
83 public const decimal MinusOne = -1;
84 public const decimal One = 1;
85 public const decimal Zero = 0;
88 private static readonly Decimal MaxValueDiv10 = MaxValue / 10;
90 // maximal decimal value as double
91 private static readonly double dDecMaxValue = 7.922816251426433759354395033e28;
92 // epsilon decimal value as double
93 private static readonly double dDecEpsilon = 0.5e-28; // == 0.5 * 1 / 10^28
96 private const int DECIMAL_DIVIDE_BY_ZERO = 5;
97 private const uint MAX_SCALE = 28;
98 private const int iMAX_SCALE = 28;
99 private const uint SIGN_FLAG = 0x80000000;
100 private const uint SCALE_MASK = 0x00FF0000;
101 private const int SCALE_SHIFT = 16;
102 private const uint RESERVED_SS32_BITS = 0x7F00FFFF;
104 // internal representation of decimal
110 public Decimal(int lo, int mid, int hi, bool isNegative, byte scale)
115 this.mid = (uint) mid;
118 if (scale > MAX_SCALE)
120 throw new ArgumentOutOfRangeException (Locale.GetText ("scale must be between 0 and 28"));
124 flags <<= SCALE_SHIFT;
125 if (isNegative) flags |= SIGN_FLAG;
129 public Decimal(int val)
137 lo = ((uint)~val) + 1;
147 [CLSCompliant(false)]
148 public Decimal(uint val)
151 flags = hi = mid = 0;
154 public Decimal(long val)
162 ulong u = ((ulong)~val) + 1;
164 mid = (uint)(u >> 32);
169 ulong u = (ulong)val;
171 mid = (uint)(u >> 32);
176 [CLSCompliant(false)]
177 public Decimal(ulong uval)
183 mid = (uint)(uval >> 32);
187 public Decimal (float val)
189 if (val > (float)Decimal.MaxValue || val < (float)Decimal.MinValue) {
190 throw new OverflowException (Locale.GetText (
191 "Value {0} is greater than Decimal.MaxValue or less than Decimal.MinValue", val));
193 // we must respect the precision (double2decimal doesn't)
194 Decimal d = Decimal.Parse (val.ToString (CultureInfo.InvariantCulture),
195 NumberStyles.Float, CultureInfo.InvariantCulture);
202 public Decimal (double val)
204 if (val > (double)Decimal.MaxValue || val < (double)Decimal.MinValue) {
205 throw new OverflowException (Locale.GetText (
206 "Value {0} is greater than Decimal.MaxValue or less than Decimal.MinValue", val));
208 // we must respect the precision (double2decimal doesn't)
209 Decimal d = Decimal.Parse (val.ToString (CultureInfo.InvariantCulture),
210 NumberStyles.Float, CultureInfo.InvariantCulture);
217 public Decimal(int[] bits)
221 throw new ArgumentNullException(Locale.GetText ("Bits is a null reference"));
224 if (bits.GetLength(0) != 4)
226 throw new ArgumentException(Locale.GetText ("bits does not contain four values"));
231 mid = (uint) bits[1];
233 flags = (uint) bits[3];
234 byte scale = (byte)(flags >> SCALE_SHIFT);
235 if (scale > MAX_SCALE || (flags & RESERVED_SS32_BITS) != 0)
237 throw new ArgumentException(Locale.GetText ("Invalid bits[3]"));
242 public static decimal FromOACurrency(long cy)
244 return (decimal)cy / (decimal)10000;
247 public static int[] GetBits(Decimal d)
251 return new int[] { (int)d.lo, (int)d.mid, (int)d.hi,
256 public static Decimal Negate(Decimal d)
258 d.flags ^= SIGN_FLAG;
263 public static Decimal Add(Decimal d1, Decimal d2)
265 if (decimalIncr(ref d1, ref d2) == 0)
268 throw new OverflowException(Locale.GetText ("Overflow on adding decimal number"));
271 public static Decimal Subtract(Decimal d1, Decimal d2)
273 d2.flags ^= SIGN_FLAG;
274 int result = decimalIncr(ref d1, ref d2);
278 throw new OverflowException(Locale.GetText ("Overflow on subtracting decimal numbers ("+result+")"));
281 public override int GetHashCode ()
283 return (int) (flags ^ hi ^ lo ^ mid);
286 public static Decimal operator +(Decimal d1, Decimal d2)
291 public static Decimal operator --(Decimal d)
293 return Add(d, MinusOne);
296 public static Decimal operator ++(Decimal d)
301 public static Decimal operator -(Decimal d1, Decimal d2)
303 return Subtract(d1, d2);
306 public static Decimal operator -(Decimal d)
311 public static Decimal operator +(Decimal d)
316 public static Decimal operator *(Decimal d1, Decimal d2)
318 return Multiply(d1, d2);
321 public static Decimal operator /(Decimal d1, Decimal d2)
323 return Divide(d1, d2);
326 public static Decimal operator %(Decimal d1, Decimal d2)
328 return Remainder(d1, d2);
331 private static ulong u64 (Decimal value)
335 decimalFloorAndTrunc (ref value, 0);
336 if (decimal2UInt64 (ref value, out result) != 0) {
337 throw new System.OverflowException ();
342 private static long s64 (Decimal value)
346 decimalFloorAndTrunc (ref value, 0);
347 if (decimal2Int64 (ref value, out result) != 0) {
348 throw new System.OverflowException ();
353 public static explicit operator byte (Decimal val)
355 ulong result = u64 (val);
356 return checked ((byte) result);
359 [CLSCompliant (false)]
360 public static explicit operator sbyte (Decimal val)
362 long result = s64 (val);
363 return checked ((sbyte) result);
366 public static explicit operator char (Decimal val)
368 ulong result = u64 (val);
369 return checked ((char) result);
372 public static explicit operator short (Decimal val)
374 long result = s64 (val);
375 return checked ((short) result);
378 [CLSCompliant (false)]
379 public static explicit operator ushort (Decimal val)
381 ulong result = u64 (val);
382 return checked ((ushort) result);
385 public static explicit operator int (Decimal val)
387 long result = s64 (val);
388 return checked ((int) result);
391 [CLSCompliant(false)]
392 public static explicit operator uint (Decimal val)
394 ulong result = u64 (val);
395 return checked ((uint) result);
398 public static explicit operator long (Decimal val)
403 [CLSCompliant(false)]
404 public static explicit operator ulong (Decimal val)
409 public static implicit operator Decimal(byte val)
411 return new Decimal(val);
414 [CLSCompliant(false)]
415 public static implicit operator Decimal(sbyte val)
417 return new Decimal(val);
420 public static implicit operator Decimal(short val)
422 return new Decimal(val);
425 [CLSCompliant(false)]
426 public static implicit operator Decimal(ushort val)
428 return new Decimal(val);
431 public static implicit operator Decimal(char val)
433 return new Decimal(val);
436 public static implicit operator Decimal(int val)
438 return new Decimal(val);
441 [CLSCompliant(false)]
442 public static implicit operator Decimal(uint val)
444 return new Decimal(val);
447 public static implicit operator Decimal(long val)
449 return new Decimal(val);
452 [CLSCompliant(false)]
453 public static implicit operator Decimal(ulong val)
455 return new Decimal(val);
458 public static explicit operator Decimal(float val)
460 return new Decimal(val);
463 public static explicit operator Decimal(double val)
465 return new Decimal(val);
468 public static explicit operator float(Decimal val)
470 return (float) (double) val;
473 public static explicit operator double(Decimal val)
475 return decimal2double(ref val);
479 public static bool operator !=(Decimal d1, Decimal d2)
481 return !Equals(d1, d2);
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 decimalCompare(ref d1, ref d2) > 0;
494 public static bool operator >=(Decimal d1, Decimal d2)
496 return decimalCompare(ref d1, ref d2) >= 0;
499 public static bool operator <(Decimal d1, Decimal d2)
501 return decimalCompare(ref d1, ref d2) < 0;
504 public static bool operator <=(Decimal d1, Decimal d2)
506 return decimalCompare(ref d1, ref d2) <= 0;
509 public static bool Equals(Decimal d1, Decimal d2)
511 return decimalCompare(ref d1, ref d2) == 0;
514 public override bool Equals(object o)
519 return Equals((Decimal) o, this);
522 // avoid unmanaged call
523 private bool IsZero ()
525 return ((hi == 0) && (lo == 0) && (mid == 0));
528 // avoid unmanaged call
529 private bool IsNegative ()
531 return ((flags & 0x80000000) == 0x80000000);
534 public static Decimal Floor(Decimal d)
536 decimalFloorAndTrunc(ref d, 1);
540 public static Decimal Truncate(Decimal d)
542 decimalFloorAndTrunc(ref d, 0);
546 public static Decimal Round (Decimal d, int decimals)
549 return Round (d, decimals, MidpointRounding.ToEven);
552 public static Decimal Round (Decimal d, int decimals, MidpointRounding mode)
554 if ((mode != MidpointRounding.ToEven) && (mode != MidpointRounding.AwayFromZero))
555 throw new ArgumentException ("The value '" + mode + "' is not valid for this usage of the type MidpointRounding.", "mode");
558 if (decimals < 0 || decimals > 28) {
559 throw new ArgumentOutOfRangeException ("decimals", "[0,28]");
562 bool negative = d.IsNegative ();
564 d.flags ^= SIGN_FLAG;
566 // Moved from Math.cs because it's easier to fix the "sign"
567 // issue here :( as the logic is OK only for positive numbers
568 decimal p = (decimal) Math.Pow (10, decimals);
569 decimal int_part = Decimal.Floor (d);
570 decimal dec_part = d - int_part;
571 dec_part *= 10000000000000000000000000000M;
572 dec_part = Decimal.Floor(dec_part);
573 dec_part /= (10000000000000000000000000000M / p);
575 dec_part = Math.Round (dec_part, mode);
577 dec_part = Math.Round (dec_part);
580 decimal result = int_part + dec_part;
582 // that fixes the precision/scale (which we must keep for output)
583 // (moved and adapted from System.Data.SqlTypes.SqlMoney)
584 long scaleDiff = decimals - ((result.flags & 0x7FFF0000) >> 16);
587 // note: here we always work with positive numbers
588 while (scaleDiff > 0) {
589 if (result > MaxValueDiv10)
595 else if (scaleDiff < 0) {
596 while (scaleDiff < 0) {
601 result.flags = (uint)((decimals - scaleDiff) << SCALE_SHIFT);
604 result.flags ^= SIGN_FLAG;
609 public static Decimal Round (Decimal d)
611 return Math.Round (d);
614 public static Decimal Round (Decimal d, MidpointRounding mode)
616 return Math.Round (d, mode);
620 public static Decimal Multiply (Decimal d1, Decimal d2)
622 if (d1.IsZero () || d2.IsZero ())
625 if (decimalMult (ref d1, ref d2) != 0)
626 throw new OverflowException ();
630 public static Decimal Divide (Decimal d1, Decimal d2)
633 throw new DivideByZeroException ();
639 d1.flags ^= SIGN_FLAG;
641 return Decimal.MinusOne;
642 d1.flags ^= SIGN_FLAG;
645 if (decimalDiv (out result, ref d1, ref d2) != 0)
646 throw new OverflowException ();
651 public static Decimal Remainder (Decimal d1, Decimal d2)
654 throw new DivideByZeroException ();
658 bool negative = d1.IsNegative ();
660 d1.flags ^= SIGN_FLAG;
661 if (d2.IsNegative ())
662 d2.flags ^= SIGN_FLAG;
672 if (decimalIntDiv (out result, ref d1, ref d2) != 0)
673 throw new OverflowException ();
675 // FIXME: not really performant here
676 result = d1 - result * d2;
680 result.flags ^= SIGN_FLAG;
685 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
687 public static int Compare(Decimal d1, Decimal d2)
689 return decimalCompare(ref d1, ref d2);
692 public int CompareTo(object val)
697 if (!(val is Decimal))
698 throw new ArgumentException (Locale.GetText ("Value is not a System.Decimal"));
700 Decimal d2 = (Decimal)val;
701 return decimalCompare(ref this, ref d2);
705 public int CompareTo(Decimal value)
707 return decimalCompare(ref this, ref value);
710 public bool Equals(Decimal value)
712 return Equals(value, this);
715 public static Decimal Ceiling(Decimal d)
717 return Math.Ceiling (d);
721 public static Decimal Parse(string s)
723 return Parse(s, NumberStyles.Number, null);
726 public static Decimal Parse(string s, NumberStyles style)
728 return Parse(s, style, null);
731 public static Decimal Parse(string s, IFormatProvider provider)
733 return Parse(s, NumberStyles.Number, provider);
736 static void ThrowAtPos (int pos)
738 throw new FormatException (String.Format (Locale.GetText ("Invalid character at position {0}"), pos));
741 static void ThrowInvalidExp ()
743 throw new FormatException (Locale.GetText ("Invalid exponent"));
746 private static string stripStyles(string s, NumberStyles style, NumberFormatInfo nfi,
747 out int decPos, out bool isNegative, out bool expFlag, out int exp, bool throwex)
754 bool hasSign = false;
755 bool hasOpeningParentheses = false;
756 bool hasDecimalPoint = false;
757 bool allowedLeadingWhiteSpace = ((style & NumberStyles.AllowLeadingWhite) != 0);
758 bool allowedTrailingWhiteSpace = ((style & NumberStyles.AllowTrailingWhite) != 0);
759 bool allowedLeadingSign = ((style & NumberStyles.AllowLeadingSign) != 0);
760 bool allowedTrailingSign = ((style & NumberStyles.AllowTrailingSign) != 0);
761 bool allowedParentheses = ((style & NumberStyles.AllowParentheses) != 0);
762 bool allowedThousands = ((style & NumberStyles.AllowThousands) != 0);
763 bool allowedDecimalPoint = ((style & NumberStyles.AllowDecimalPoint) != 0);
764 bool allowedExponent = ((style & NumberStyles.AllowExponent) != 0);
766 /* get rid of currency symbol */
767 bool hasCurrency = false;
768 if ((style & NumberStyles.AllowCurrencySymbol) != 0)
770 int index = s.IndexOf(nfi.CurrencySymbol);
773 s = s.Remove(index, nfi.CurrencySymbol.Length);
778 string decimalSep = (hasCurrency) ? nfi.CurrencyDecimalSeparator : nfi.NumberDecimalSeparator;
779 string groupSep = (hasCurrency) ? nfi.CurrencyGroupSeparator : nfi.NumberGroupSeparator;
784 StringBuilder sb = new StringBuilder(len);
790 if (Char.IsDigit(ch))
792 break; // end of leading
794 else if (allowedLeadingWhiteSpace && Char.IsWhiteSpace(ch))
798 else if (allowedParentheses && ch == '(' && !hasSign && !hasOpeningParentheses)
800 hasOpeningParentheses = true;
805 else if (allowedLeadingSign && ch == nfi.NegativeSign[0] && !hasSign)
807 int slen = nfi.NegativeSign.Length;
808 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
815 else if (allowedLeadingSign && ch == nfi.PositiveSign[0] && !hasSign)
817 int slen = nfi.PositiveSign.Length;
818 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
824 else if (allowedDecimalPoint && ch == decimalSep[0])
826 int slen = decimalSep.Length;
827 if (slen != 1 && s.IndexOf(decimalSep, pos, slen) != pos)
847 throw new FormatException(Locale.GetText ("No digits found"));
856 if (Char.IsDigit(ch))
861 else if (allowedThousands && ch == groupSep[0])
863 int slen = groupSep.Length;
864 if (slen != 1 && s.IndexOf(groupSep, pos, slen) != pos)
873 else if (allowedDecimalPoint && ch == decimalSep[0] && !hasDecimalPoint)
875 int slen = decimalSep.Length;
876 if (slen == 1 || s.IndexOf(decimalSep, pos, slen) == pos)
879 hasDecimalPoint = true;
893 if (allowedExponent && Char.ToUpperInvariant (ch) == 'E')
904 bool isNegativeExp = false;
905 if (ch == nfi.PositiveSign[0])
907 int slen = nfi.PositiveSign.Length;
908 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
919 else if (ch == nfi.NegativeSign[0])
921 int slen = nfi.NegativeSign.Length;
922 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
931 isNegativeExp = true;
935 if (!Char.IsDigit(ch)){
944 while (pos < len && Char.IsDigit(s[pos]))
950 if (isNegativeExp) exp *= -1;
958 if (allowedTrailingWhiteSpace && Char.IsWhiteSpace(ch))
962 else if (allowedParentheses && ch == ')' && hasOpeningParentheses)
964 hasOpeningParentheses = false;
967 else if (allowedTrailingSign && ch == nfi.NegativeSign[0] && !hasSign)
969 int slen = nfi.NegativeSign.Length;
970 if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
977 else if (allowedTrailingSign && ch == nfi.PositiveSign[0] && !hasSign)
979 int slen = nfi.PositiveSign.Length;
980 if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
995 if (hasOpeningParentheses){
997 throw new FormatException (Locale.GetText ("Closing Parentheses not found"));
1002 if (!hasDecimalPoint)
1005 return sb.ToString();
1008 public static Decimal Parse (string s, NumberStyles style, IFormatProvider provider)
1011 throw new ArgumentNullException ("s");
1013 if ((style & NumberStyles.AllowHexSpecifier) != 0)
1014 throw new ArgumentException ("Decimal.TryParse does not accept AllowHexSpecifier", "style");
1017 PerformParse (s, style, provider, out result, true);
1022 public static bool TryParse (string s, out Decimal result)
1028 return PerformParse (s, NumberStyles.Number, null, out result, false);
1031 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out decimal result)
1033 if (s == null || (style & NumberStyles.AllowHexSpecifier) != 0){
1038 return PerformParse (s, style, provider, out result, false);
1042 static bool PerformParse (string s, NumberStyles style, IFormatProvider provider, out Decimal res, bool throwex)
1044 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (provider);
1047 bool isNegative, expFlag;
1048 s = stripStyles(s, style, nfi, out iDecPos, out isNegative, out expFlag, out exp, throwex);
1056 throw new Exception (Locale.GetText ("Error in System.Decimal.Parse"));
1061 // first we remove leading 0
1064 while ((i < iDecPos) && (s [i] == '0'))
1066 if ((i > 1) && (len > 1)) {
1067 s = s.Substring (i, len - i);
1071 // first 0. may not be here but is part of the maximum length
1072 int max = ((iDecPos == 0) ? 27 : 28);
1074 if (len >= max + 1) {
1075 // number lower than MaxValue (base-less) can have better precision
1076 if (String.Compare (s, 0, "79228162514264337593543950335", 0, max + 1,
1077 false, CultureInfo.InvariantCulture) <= 0) {
1082 // then we trunc the string
1083 if ((len > max) && (iDecPos < len)) {
1084 int round = (s [max] - '0');
1085 s = s.Substring (0, max);
1087 bool addone = false;
1091 else if (round == 5) {
1096 // banker rounding applies :(
1097 int previous = (s [max - 1] - '0');
1098 addone = ((previous & 0x01) == 0x01);
1102 char[] array = s.ToCharArray ();
1105 int b = (array [p] - '0');
1106 if (array [p] != '9') {
1107 array [p] = (char)(b + '1');
1114 if ((p == -1) && (array [0] == '0')) {
1116 s = "1".PadRight (iDecPos, '0');
1119 s = new String (array);
1124 // always work in positive (rounding issues)
1125 if (string2decimal (out result, s, (uint)iDecPos, 0) != 0){
1127 throw new OverflowException ();
1133 if (decimalSetExponent (ref result, exp) != 0){
1135 throw new OverflowException ();
1142 result.flags ^= SIGN_FLAG;
1148 public TypeCode GetTypeCode ()
1150 return TypeCode.Decimal;
1153 public static byte ToByte (decimal value)
1155 if (value > Byte.MaxValue || value < Byte.MinValue)
1156 throw new OverflowException (Locale.GetText (
1157 "Value is greater than Byte.MaxValue or less than Byte.MinValue"));
1159 // return truncated value
1160 return (byte)(Decimal.Truncate (value));
1163 public static double ToDouble (decimal value)
1165 return Convert.ToDouble (value);
1168 public static short ToInt16 (decimal value)
1170 if (value > Int16.MaxValue || value < Int16.MinValue)
1171 throw new OverflowException (Locale.GetText (
1172 "Value is greater than Int16.MaxValue or less than Int16.MinValue"));
1174 // return truncated value
1175 return (Int16)(Decimal.Truncate (value));
1178 public static int ToInt32 (decimal value)
1180 if (value > Int32.MaxValue || value < Int32.MinValue)
1181 throw new OverflowException (Locale.GetText (
1182 "Value is greater than Int32.MaxValue or less than Int32.MinValue"));
1184 // return truncated value
1185 return (Int32)(Decimal.Truncate (value));
1188 public static long ToInt64 (decimal value)
1190 if (value > Int64.MaxValue || value < Int64.MinValue)
1191 throw new OverflowException (Locale.GetText (
1192 "Value is greater than Int64.MaxValue or less than Int64.MinValue"));
1194 // return truncated value
1195 return (Int64)(Decimal.Truncate (value));
1198 public static long ToOACurrency (decimal value)
1200 return (long) (value * 10000);
1203 [CLSCompliant(false)]
1204 public static sbyte ToSByte (decimal value)
1206 if (value > SByte.MaxValue || value < SByte.MinValue)
1207 throw new OverflowException (Locale.GetText (
1208 "Value is greater than SByte.MaxValue or less than SByte.MinValue"));
1210 // return truncated value
1211 return (SByte)(Decimal.Truncate (value));
1214 public static float ToSingle (decimal value)
1216 return Convert.ToSingle (value);
1219 [CLSCompliant(false)]
1220 public static ushort ToUInt16 (decimal value)
1222 if (value > UInt16.MaxValue || value < UInt16.MinValue)
1223 throw new OverflowException (Locale.GetText (
1224 "Value is greater than UInt16.MaxValue or less than UInt16.MinValue"));
1226 // return truncated value
1227 return (UInt16)(Decimal.Truncate (value));
1230 [CLSCompliant(false)]
1231 public static uint ToUInt32 (decimal value)
1233 if (value > UInt32.MaxValue || value < UInt32.MinValue)
1234 throw new OverflowException (Locale.GetText (
1235 "Value is greater than UInt32.MaxValue or less than UInt32.MinValue"));
1237 // return truncated value
1238 return (UInt32)(Decimal.Truncate (value));
1241 [CLSCompliant(false)]
1242 public static ulong ToUInt64 (decimal value)
1244 if (value > UInt64.MaxValue || value < UInt64.MinValue)
1245 throw new OverflowException (Locale.GetText (
1246 "Value is greater than UInt64.MaxValue or less than UInt64.MinValue"));
1248 // return truncated value
1249 return (UInt64)(Decimal.Truncate (value));
1252 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
1254 return Convert.ToType (this, conversionType, provider);
1257 bool IConvertible.ToBoolean (IFormatProvider provider)
1259 return Convert.ToBoolean (this);
1262 byte IConvertible.ToByte (IFormatProvider provider)
1264 return Convert.ToByte (this);
1267 char IConvertible.ToChar (IFormatProvider provider)
1269 throw new InvalidCastException ();
1272 DateTime IConvertible.ToDateTime (IFormatProvider provider)
1274 throw new InvalidCastException ();
1277 decimal IConvertible.ToDecimal (IFormatProvider provider)
1282 double IConvertible.ToDouble (IFormatProvider provider)
1284 return Convert.ToDouble (this);
1287 short IConvertible.ToInt16 (IFormatProvider provider)
1289 return Convert.ToInt16 (this);
1292 int IConvertible.ToInt32 (IFormatProvider provider)
1294 return Convert.ToInt32 (this);
1297 long IConvertible.ToInt64 (IFormatProvider provider)
1299 return Convert.ToInt64 (this);
1302 sbyte IConvertible.ToSByte (IFormatProvider provider)
1304 return Convert.ToSByte (this);
1307 float IConvertible.ToSingle (IFormatProvider provider)
1309 return Convert.ToSingle (this);
1312 ushort IConvertible.ToUInt16 (IFormatProvider provider)
1314 return Convert.ToUInt16 (this);
1317 uint IConvertible.ToUInt32 (IFormatProvider provider)
1319 return Convert.ToUInt32 (this);
1322 ulong IConvertible.ToUInt64 (IFormatProvider provider)
1324 return Convert.ToUInt64 (this);
1327 public string ToString (string format, IFormatProvider provider)
1329 return NumberFormatter.NumberToString (format, this, provider);
1332 public override string ToString()
1334 return ToString("G", null);
1337 public string ToString(string format)
1339 return ToString(format, null);
1342 public string ToString(IFormatProvider provider)
1344 return ToString("G", provider);
1348 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1349 private static extern int decimal2UInt64(ref Decimal val,
1352 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1353 private static extern int decimal2Int64(ref Decimal val,
1356 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1357 private static extern int double2decimal(out Decimal erg,
1358 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,
1380 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1381 private static extern void decimalRound(ref Decimal val, int decimals);
1383 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1384 private static extern int decimalMult(ref Decimal pd1, ref Decimal pd2);
1386 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1387 private static extern int decimalDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1389 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1390 private static extern int decimalIntDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1392 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1393 private static extern int decimalCompare(ref Decimal d1, ref Decimal d2);
1395 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1396 [DllImport("libdec", EntryPoint="decimal2UInt64")]
1397 private static extern int decimal2UInt64(ref Decimal val,
1400 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1401 [DllImport("libdec", EntryPoint="decimal2Int64")]
1402 private static extern int decimal2Int64(ref Decimal val,
1405 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1406 [DllImport("libdec", EntryPoint="double2decimal")]
1407 private static extern int double2decimal(out Decimal erg,
1408 double val, int digits);
1410 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1411 [DllImport("libdec", EntryPoint="decimalIncr")]
1412 private static extern int decimalIncr(ref Decimal d1, ref Decimal d2);
1414 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1415 [DllImport("libdec", EntryPoint="decimal2string")]
1416 internal static extern int decimal2string(ref Decimal val,
1417 int digits, int decimals,
1418 [MarshalAs(UnmanagedType.LPWStr)]StringBuilder bufDigits,
1419 int bufSize, out int decPos, out int sign);
1421 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1422 [DllImport("libdec", EntryPoint="string2decimal")]
1423 internal static extern int string2decimal(out Decimal val,
1424 [MarshalAs(UnmanagedType.LPWStr)]String sDigits,
1425 uint decPos, int sign);
1427 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1428 [DllImport("libdec", EntryPoint="decimalSetExponent")]
1429 internal static extern int decimalSetExponent(ref Decimal val, int exp);
1431 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1432 [DllImport("libdec", EntryPoint="decimal2double")]
1433 private static extern double decimal2double(ref Decimal val);
1435 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1436 [DllImport("libdec", EntryPoint="decimalFloorAndTrunc")]
1437 private static extern void decimalFloorAndTrunc(ref Decimal val,
1440 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1441 [DllImport("libdec", EntryPoint="decimalRound")]
1442 private static extern void decimalRound(ref Decimal val, int decimals);
1444 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1445 [DllImport("libdec", EntryPoint="decimalMult")]
1446 private static extern int decimalMult(ref Decimal pd1, ref Decimal pd2);
1448 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1449 [DllImport("libdec", EntryPoint="decimalDiv")]
1450 private static extern int decimalDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1452 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1453 [DllImport("libdec", EntryPoint="decimalIntDiv")]
1454 private static extern int decimalIntDiv(out Decimal pc, ref Decimal pa, ref Decimal pb);
1456 //![MethodImplAttribute(MethodImplOptions.InternalCall)]
1457 [DllImport("libdec", EntryPoint="decimalCompare")]
1458 private static extern int decimalCompare(ref Decimal d1, ref Decimal d2);