Is there a BigFloat class in C#?

前端 未结 1 1662
你的背包
你的背包 2020-11-27 07:37

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

相关标签:
1条回答
  • 2020-11-27 08:39

    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.

    0 讨论(0)
提交回复
热议问题