在C#中是否有一个BigFloat类?

15

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

你确定你不是在寻找BigRat吗? - Cameron
不,也没有标准的BigDecimal。:( (但是他们有Complex,耶!) - Kirk Woll
@RandolphWest Double类型与int相同,只是能够处理更大的数字。 - jb.
@Cameron 什么是BigRat?有链接吗? - jb.
2个回答

18

也许您正在寻找 BigRational? Microsoft在CodePlex的BCL项目下发布了它。不确定它是否适合您的需求。

它将数字保留为有理数。您可以通过强制转换或一些乘法来获取带有小数值的字符串。

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

或者使用这样一个简单的扩展方法(有点):
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,就像十进制或双精度浮点数一样。

它保持答案为有理数形式吗?你能得到一个小数吗?这可能有效。谢谢链接。 - jb.
我正在使用一些非常大的数字,但是你们两种转换方法都给我零。 - jb.
@jb. - 抱歉让你等这么久,但我终于搞定了。我的新扩展方法可以将任何BigRational数转换为正确的十进制字符串。它比我希望的要复杂一些,而且我确信有更快或更简单的方法来做到这一点。然而,我不是数学家,所以我想说我不知道自己在做什么。希望这能帮到你。 - Christopher Currens

1

如果有一个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;

这个有效并且给了我们这个类型:

One Third

你可以直接使用 NuGet 下载 BigRational,其中包括了许多实现方案,包括微软的一种。

1
为了避免可能的OOM,似乎可以通过“懒计算”的方式来计算结果,这样它只会计算被要求的足够位数。 - jb.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接