Is there a BigFloat class in C#?
Asked Answered
W

2

16

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);
Waite answered 28/4, 2012 at 0:9 Comment(5)
Are you sure you aren't looking for a BigRat?Disburden
No, no standard BigDecimal either. :( (but they got Complex covered, yay!)Sibyl
@RandolphWest Double has the same limitations as int, albeit at a higher number.Waite
@Disburden whats BigRat? got a link?Waite
possible duplicate of Calculating big float number fast like 0.4 ^ 100000000 ,, any ideas?Ammonal
M
18

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.

Messere answered 28/4, 2012 at 0:16 Comment(3)
it keeps the answer in rational form? can you get a decimal out of it? This might work. thanks for the linkWaite
I'm using some pretty giant numbers, but both your ways to convert it are giving me zero'sWaite
@Waite - Sorry it took me so long, but I've finally got it figured out. My new extension method will convert any BigRational number to a decimal string properly. It was a little more complicated than I hoped it would be, and I'm positive that there is either a faster or easier way of doing this. However, I'm no mathematician, so I think it's safe to say I have no idea what I'm doing. Hope this helps.Messere
I
1

It should be considered what the implications would be if there were a BigFloat type.

BigFloat x = 1.0;
BigFloat y = 3.0;
BigFloat z = x / y;

The answer would be 0.333333333333333333333333333333333333333333333333333333 recurring. Forever. Infinite. Out of Memory Error.

It is easy to construct an infinite BigFloat.

However, if you are happy to stick to rational numbers, those express by the dividing one integer with another than you can use BigInteger to build a BigRational type that can provide arbitrary precision for representing any real number.

BigRational x = 1;
BigRational y = 3;
BigRational z = x / y;

This works and gives us this type:

One Third

You can just NuGet BigRational and you'll find many implementations, including once from Microsoft.

Invasive answered 27/11, 2020 at 6:47 Comment(1)
To avoid the possible OOM, it seems it would be possible to 'lazy calculate' the result in such a way that it would only calculate enough digits that are being asked for.Waite

© 2022 - 2024 — McMap. All rights reserved.