How to know the repeating decimal in a fraction?

后端 未结 5 1622
庸人自扰
庸人自扰 2020-11-29 09:42

I already know when a fraction is repeating decimals. Here is the function.

public bool IsRepeatingDecimal
{
    get
    {
        if (Numerator % Denominato         


        
5条回答
  •  醉话见心
    2020-11-29 10:16

    I came here expecting to be able to copy & paste the code to do this, but it didn't exist. So after reading @Patrick87's answer, I went ahead and coded it up. I spent some time testing it thoroughly and giving things a nice name. I thought I would leave it here so others don't have to waste their time.

    Features: If the decimal terminates, it handles that. It calculates the period and puts that in a separate variable called period, in case you want to know the length of the reptend.

    Limitations: It will fail if the transient + reptend is longer than can be represented by a System.Decimal.

    public static string FormatDecimalExpansion(RationalNumber value)
    {
        RationalNumber currentValue = value;
    
        string decimalString = value.ToDecimal().ToString();
        int currentIndex = decimalString.IndexOf('.');
    
        Dictionary dict = new Dictionary();
        while (!dict.ContainsKey(currentValue))
        {
            dict.Add(currentValue, currentIndex);
    
            int rem = currentValue.Numerator % currentValue.Denominator;
            int carry = rem * 10;
    
            if (rem == 0) // Terminating decimal
            {
                return decimalString;
            }
    
            currentValue = new RationalNumber(carry, currentValue.Denominator);
            currentIndex++;
        }
    
        int startIndex = dict[currentValue];
        int endIndex = currentIndex;
        int period = (endIndex - startIndex); // The period is the length of the reptend
    
        if (endIndex >= decimalString.Length)
        {
            throw new ArgumentOutOfRangeException(nameof(value),
                "The value supplied has a decimal expansion that is longer" +
                $" than can be represented by value of type {nameof(System.Decimal)}.");
        }
    
        string transient = decimalString.Substring(0, startIndex);
        string reptend = decimalString.Substring(startIndex, period);
    
        return transient + $"({reptend})";
    }
    

    And for good measure, I will include my RationalNumber class. Note: It inherits from IEquatable so that it works correctly with the dictionary:


    public struct RationalNumber : IEquatable
    {
        public int Numerator;
        public int Denominator;
    
        public RationalNumber(int numerator, int denominator)
        {
            Numerator = numerator;
            Denominator = denominator;
        }
    
        public decimal ToDecimal()
        {
            return Decimal.Divide(Numerator, Denominator);
        }
    
        public bool Equals(RationalNumber other)
        {
            return (Numerator == other.Numerator && Denominator == other.Denominator);
        }
    
        public override int GetHashCode()
        {
            return new Tuple(Numerator, Denominator).GetHashCode();
        }
    
        public override string ToString()
        {
            return $"{Numerator}/{Denominator}";
        }
    }
    

    Enjoy!

提交回复
热议问题