Есть ли класс BigFloat в C#?

System.Numerics.BigInteger позволяет умножать большие целые числа вместе, но есть ли что-нибудь одного типа для чисел с плавающей запятой? Если нет, есть ли бесплатная библиотека, которую я могу использовать?

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

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

1 ответ

Решение

Возможно, вы ищете BigRational? Microsoft выпустила его в рамках своего проекта BCL на CodePlex. Не совсем уверен, как или если это будет соответствовать вашим потребностям.

Он держит это как рациональное число. Вы можете получить строку с десятичным значением путем приведения или умножения.

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

Или с помощью простого (ish) метода расширения, например:

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();
    }
}

Если это вне диапазона точности десятичного или двойного, они будут приведены к их соответствующим типам со значением 0.0. Кроме того, приведение к десятичному типу, когда результат находится за пределами его диапазона, вызовет OverflowException быть брошенным.

Метод расширения, который я написал (который может быть не лучшим способом для вычисления десятичного представления дроби), будет точно преобразовывать его в строку с неограниченной точностью. Однако, если число меньше запрашиваемой точности, оно вернет 0.0, как десятичное или двойное значение.

Следует подумать, каковы были бы последствия, если бы BigFloat тип.

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

Ответ был бы 0.333333333333333333333333333333333333333333333333333333повторяющийся. Навсегда. Бесконечный. Ошибка нехватки памяти.

Легко построить бесконечное BigFloat.

Однако, если вы счастливы придерживаться рациональных чисел, они выражаются делением одного целого числа на другое, чем вы можете использовать BigInteger построить BigRational тип, который может обеспечивать произвольную точность для представления любого действительного числа.

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

Это работает и дает нам такой тип:

Вы можете просто NuGet BigRational и вы найдете множество реализаций, в том числе от Microsoft.

Другие вопросы по тегам