Ejemplo n.º 1
0
        public static bool TryConvertToRationalNumber(decimal num, out IQ.RationalNumber rational)
        {
            rational = IQ.New(0, 0);

            int     wholePart     = (int)decimal.Truncate(num);
            decimal decimalPlaces = num - (decimal)wholePart;

            var numString   = decimalPlaces.ToString();
            var totalLength = numString.Length;
            var placesCount = DecimalPlacesCount(decimalPlaces);

            if (placesCount == 28)
            {
                numString     = numString.Remove(numString.Length - 1) + (int.Parse(numString.Substring(numString.Length - 1, 1)) - 1);
                decimalPlaces = decimal.Parse(numString);
            }

            bool repeatingConfirmed = false;
            bool isNegative         = decimalPlaces < 0;

            string first               = "";
            int    firstIndex          = 0;
            string second              = "";
            int    secondIndex         = 0;
            int    repeatingPartLength = 0;
            int    nonPlacesLength     = numString.Length - placesCount;
            bool   isEqualFirstTime    = false;
            int    repeatCount         = 0;
            bool   isRepeating         = true;

            for (int i = 0; i < (decimal)placesCount / 2; i++)
            {
                repeatCount         = 0;
                isRepeating         = true;
                isEqualFirstTime    = false;
                repeatingPartLength = i + 1;

                for (int j = 0; (isEqualFirstTime ? (j + 2) * repeatingPartLength : j + (2 * repeatingPartLength)) <= placesCount; j++)
                {
                    if (isEqualFirstTime)
                    {
                        secondIndex = secondIndex + repeatingPartLength;
                    }
                    else
                    {
                        firstIndex  = nonPlacesLength + j;
                        secondIndex = firstIndex + repeatingPartLength;
                    }

                    first  = numString.Substring(firstIndex, repeatingPartLength);
                    second = numString.Substring(secondIndex, repeatingPartLength);
                    if (string.Equals(first, second))
                    {
                        if (!isEqualFirstTime && firstIndex < placesCount)
                        {
                            isEqualFirstTime = true;
                        }
                        else
                        {
                            repeatCount++;
                            if (repeatCount > 2)
                            {
                                break;
                            }
                        }
                    }
                    else if (isEqualFirstTime)
                    {
                        isEqualFirstTime = false;
                        isRepeating      = false;
                    }
                }

                if (isEqualFirstTime && isRepeating)
                {
                    repeatingConfirmed = true;
                    break;
                }
            }
            if (!repeatingConfirmed)
            {
                //Try to find repeating part don't fit in decimal places
                repeatCount      = 0;
                isRepeating      = true;
                isEqualFirstTime = false;
                int lastIndexOfOccurance = 0;
                for (int i = 0; i < (decimal)placesCount / 2; i++)
                {
                    firstIndex          = totalLength;
                    repeatingPartLength = i + 1;

                    first = numString.Substring(firstIndex - repeatingPartLength, repeatingPartLength);
                    var indexOfOccurance = numString.IndexOf(first);

                    if (indexOfOccurance > 0 && indexOfOccurance != (firstIndex - repeatingPartLength))
                    {
                        lastIndexOfOccurance = indexOfOccurance;
                        if (!isEqualFirstTime)
                        {
                            isEqualFirstTime = true;
                        }
                        else
                        {
                            repeatCount++;
                        }
                    }
                    else if (i == 0)
                    {
                        isRepeating = false;
                        break;
                    }
                    else if (isEqualFirstTime)
                    {
                        var repeatingPart = numString.Substring(lastIndexOfOccurance, (firstIndex - repeatingPartLength + 1) - lastIndexOfOccurance);
                        firstIndex          = lastIndexOfOccurance;
                        repeatingPartLength = repeatingPart.Length;
                        repeatingConfirmed  = true;
                        break;
                    }
                }
            }


            if (repeatingConfirmed)
            {
                //first index = non repeating part
                //get int with Math.Truncate(decimal)
                int placesIndex = firstIndex - nonPlacesLength;
                //ulong firstMultiplier = (ulong)Math.Pow((double)10, (double)placesIndex + (double)repeatingPartLength);
                decimal firstNum        = decimalPlaces;
                decimal firstMultiplier = 1;
                for (int i = 0; i < repeatingPartLength + placesIndex; i++)
                {
                    firstNum        *= 10;
                    firstMultiplier *= 10;
                }
                //ulong secondMultiplier = (ulong)Math.Pow((double)10, (double)placesIndex);
                //decimal secondNum = secondMultiplier * decimalPlaces;

                decimal secondMultiplier = 1;
                for (int i = 0; i < repeatingPartLength; i++)
                {
                    secondMultiplier *= 10;
                }
                decimal remaininMultiplier = firstMultiplier - secondMultiplier;

                if (remaininMultiplier == 0)
                {
                    return(false);
                }
                decimal remainingNum = (decimal.Truncate(firstNum));
                decimal gcd          = GetGCD(remainingNum, remaininMultiplier);
                int     numerator    = remainingNum / gcd >= (decimal)int.MaxValue ? 0 : (int)(remainingNum / gcd);
                if (numerator == 0)
                {
                    return(false);
                }

                if (isNegative)
                {
                    numerator = -numerator;
                }
                int denominator = remaininMultiplier / gcd >= (decimal)int.MaxValue ? 0 : (int)(remaininMultiplier / gcd);
                rational = IQ.New(numerator, denominator);
                return(true);
            }
            else
            {
                decimal firstMultiplier = (ulong)Math.Pow((double)10, (double)placesCount);
                decimal firstNum        = (ulong)((decimal)firstMultiplier * decimalPlaces);
                decimal gcd             = GetGCD(firstNum, firstMultiplier);
                if (gcd > 0)
                {
                    var simplifiedFirstNum        = (int)(firstNum / gcd);
                    var simplifiedFirstMultiplier = (int)(firstMultiplier / gcd);
                    rational = IQ.New((isNegative ? -simplifiedFirstNum : simplifiedFirstNum), simplifiedFirstMultiplier);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
Ejemplo n.º 2
0
 public static RealNumber New(IQ.RationalNumber r)
 {
     return(new RealNumber(numerator: r.N, denominator: r.D));
 }