Arbitrary-Precision Decimals in C#
17,199
Solution 1
Big Decimal:
- Install the J# runtime (it's free): http://www.microsoft.com/downloads/en/details.aspx?familyid=f72c74b3-ed0e-4af8-ae63-2f0e42501be1&displaylang=en
Big Int (If you like J.D.'s solution, or want to come up with a rational number/fraction type class. That, and I somehow missed that you were looking for decimals, not ints):
- Get C# 4.0: Big integers in C#
- Get the IntX class: http://intx.codeplex.com/
Solution 2
You could implement your own based on .NET 4.0's BigInteger class. I did this for fun, it does multiplication only:
public struct BigDecimal {
public BigInteger Integer { get; set; }
public BigInteger Scale { get; set; }
public BigDecimal(BigInteger integer, BigInteger scale) : this() {
Integer = integer;
Scale = scale;
while (Scale > 0 && Integer % 10 == 0) {
Integer /= 10;
Scale -= 1;
}
}
public static implicit operator BigDecimal(decimal a) {
BigInteger integer = (BigInteger)a;
BigInteger scale = 0;
decimal scaleFactor = 1m;
while ((decimal)integer != a * scaleFactor) {
scale += 1;
scaleFactor *= 10;
integer = (BigInteger)(a * scaleFactor);
}
return new BigDecimal(integer, scale);
}
public static BigDecimal operator *(BigDecimal a, BigDecimal b) {
return new BigDecimal(a.Integer * b.Integer, a.Scale + b.Scale);
}
public override string ToString() {
string s = Integer.ToString();
if (Scale != 0) {
if (Scale > Int32.MaxValue) return "[Undisplayable]";
int decimalPos = s.Length - (int)Scale;
s = s.Insert(decimalPos, decimalPos == 0 ? "0." : ".");
}
return s;
}
}
...
decimal d1 = 254727458263237.1356246819m;
decimal d2 = 991658834219519273.110324m;
// MessageBox.Show((d1 * d2).ToString()); // OverflowException
BigDecimal bd1 = d1;
BigDecimal bd2 = d2;
MessageBox.Show((bd1 * bd2).ToString()); // 252602734305022989458258125319270.5452949161059356
Solution 3
There's always the GNU MP wrapper for .NET as long as you don't mind using the GMP.
Related videos on Youtube
Comments
-
Victor almost 2 years
Possible Duplicates:
Big integers in C#
C# unlimited significant decimal digits (arbitrary precision) without javaI read the question at Arbitrary precision decimals in C#? but I don't have the J# library. I need a library for arbitrary precision decimals with C#.
-
Gabe over 13 yearsSince neither of the proposed duplicates actually answers the question, I'm voting to reopen. The other answers are just to use
decimal
,BigInteger
, or the J# libraries. -
Ben Voigt over 13 yearsThe J# runtime library IS a library for arbitrary precision decimals in any .NET language, C# included.
-
-
Ben Voigt over 13 yearsI suggest using
s.Insert(decimalPos, ".")
instead of calling substring twice and concatenating. -
Ben Voigt over 13 yearsAlso, using
BitInteger
for scale seems overkill. You really think there's a need to support numbers outside the range 10**(-263) to bigint * 10**(263 - 1) ??? -
Gabe over 13 years
BigInteger
andIntX
are integer-only; they have no support for decimals. -
Merlyn Morgan-Graham over 13 years@Gabe: Ugh, that's true. Well, J# is free at least :)
-
Gabe over 13 yearsThis is actually pretty good, but
BigDecimal
should probably be astruct
and, as Ben suggested, the scale should probably be anint
. -
Gigo over 11 yearsI really liked that idea and completed the draft to support all basic operators, see my answer here: stackoverflow.com/a/13813535/804614
-
Protiguous over 2 yearsLink seems dead.