Search code examples
c#numericbigfloat

Is there a BigFloat class in C#?


System.Numerics.BigInteger lets you multiply large integers together, but is there anything of the same type for floating point numbers? If not, is there a free library I can use?

//this but with floats
System.Numerics.BigInteger maxint = new BigInteger(int.MaxValue);

System.Numerics.BigInteger big = maxint * maxint * maxint;
System.Console.WriteLine(big);

Solution

  • Perhaps you're looking for BigRational? Microsoft released it under their BCL project on CodePlex. Not actually sure how or if it will fit your needs.

    It keeps it as a rational number. You can get the a string with the decimal value either by casting or some multiplication.

    var r = new BigRational(5000, 3768);
    Console.WriteLine((decimal)r);
    Console.WriteLine((double)r);
    

    Or with a simple(ish) extension method like this:

    public static class BigRationalExtensions
    {
        public static string ToDecimalString(this BigRational r, int precision)
        {
            var fraction = r.GetFractionPart();
    
            // Case where the rational number is a whole number
            if(fraction.Numerator == 0 && fraction.Denominator == 1)
            {
                return r.GetWholePart() + ".0";
            }
    
            var adjustedNumerator = (fraction.Numerator
                                               * BigInteger.Pow(10, precision));
            var decimalPlaces = adjustedNumerator / fraction.Denominator;
    
            // Case where precision wasn't large enough.
            if(decimalPlaces == 0)
            {
                return "0.0";
            }
    
            // Give it the capacity for around what we should need for 
            // the whole part and total precision
            // (this is kinda sloppy, but does the trick)
            var sb = new StringBuilder(precision + r.ToString().Length);
    
            bool noMoreTrailingZeros = false;
            for (int i = precision; i > 0; i--)
            {
                if(!noMoreTrailingZeros)
                {
                    if ((decimalPlaces%10) == 0)
                    {
                        decimalPlaces = decimalPlaces/10;
                        continue;
                    }
    
                    noMoreTrailingZeros = true;
                }
    
                // Add the right most decimal to the string
                sb.Insert(0, decimalPlaces%10);
                decimalPlaces = decimalPlaces/10;
            }
    
            // Insert the whole part and decimal
            sb.Insert(0, ".");
            sb.Insert(0, r.GetWholePart());
    
            return sb.ToString();
        }
    }
    

    If it's out of the precision range of a decimal or double, they will be cast to their respective types with a value of 0.0. Also, casting to decimal, when the result is outside of its range, will cause an OverflowException to be thrown.

    The extension method I wrote (which may not be the best way to calculate a fraction's decimal representation) will accurately convert it to a string, with unlimited precision. However, if the number is smaller than the precision requested, it will return 0.0, just like decimal or double would.