Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two factorials without calculating

Is there any way to compare which factorial number is greater among two numbers without calculating?
The scenario is i am creating a c# console application which takes two factorial inputs like

123!!!!!!
456!!!  

all i want to do is to compare which factorial value is greater than other, the piece of code what i did is

try
{
    string st = Console.ReadLine();
    Int64 factCount = 0;
    while (st.Contains('!'))
    {
       factCount = st.Where(w => w == '!').Count();
       st = st.Replace('!', ' ');

    };
    decimal result = 1 ;
    for (Int64 j = 0; j < factCount; j++)
    {
        UInt64 num = Convert.ToUInt64(st.Trim());
        for (UInt64 x = num; x > 0; x--)
        {
            result = result * x;
        }
    }
    if (factCount == 0)
    {
        result = Convert.ToUInt64(st.Trim());
    }


    string st2 = Console.ReadLine();
    Int64 factCount2 = 0;
    while (st2.Contains('!'))
    {
        factCount2 = st2.Where(w => w == '!').Count();
        st2 = st2.Replace('!', ' ');
    };
    decimal result2 = 1;
    for (Int64 j = 0; j < factCount2; j++)
    {
        UInt64 num = Convert.ToUInt64(st.Trim());
        for (UInt64 x = num; x > 0; x--)
        {
            result2 = result2 * x;
        }
    }
    if (factCount2 == 0)
    {
        result2 = Convert.ToUInt64(st2.Trim());
    }

    if (result == result2)
    {
        Console.WriteLine("x=y");
    }
    else if (result < result2)
    {
        Console.WriteLine("x<y");
    }
    else if (result > result2)
    {
        Console.WriteLine("x>y");
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    Console.ReadLine();
}

but the error i'm getting is
value is too large or too small for decimal
I understood the error but is there any way to do this

Please suggest whether any other data type which accomodate value greater than decimal or is there any other way to compare these factorials

After implementing @Bathsheba suggestion i change a bit of my code

    string st = Console.ReadLine();
    int factCount = 0;
    while (st.Contains('!'))
    {
       factCount = st.Where(w => w == '!').Count();
       st = st.Replace('!', ' ');

    };

    string st2 = Console.ReadLine();
    int factCount2 = 0;
    while (st2.Contains('!'))
    {
        factCount2 = st2.Where(w => w == '!').Count();
        st2 = st2.Replace('!', ' ');
    };

    int resultFactCount = factCount - factCount2;
    decimal result = 1;
    decimal result2 = 1;

    if (resultFactCount > 0)
    {

        for (Int64 j = 0; j < resultFactCount; j++)
        {
            UInt64 num = Convert.ToUInt64(st.Trim());
            for (UInt64 x = num; x > 0; x--)
            {
                result = result * x;
            }
        }
        if (factCount == 0)
        {
            result = Convert.ToUInt64(st.Trim());
        }
        UInt64 num1 = Convert.ToUInt64(st.Trim());
        if (result == num1)
        {
            Console.WriteLine("x=y");
        }
        else if (result < num1)
        {
            Console.WriteLine("x<y");
        }
        else if (result > num1)
        {
            Console.WriteLine("x>y");
        }
    }
    else
    {
        int resultFactCount1 = System.Math.Abs(resultFactCount);
        for (Int64 j = 0; j < resultFactCount1; j++)
        {
            UInt64 num = Convert.ToUInt64(st.Trim());
            for (UInt64 x = num; x > 0; x--)
            {
                result2 = result2 * x;
            }
        }
        if (factCount2 == 0)
        {
            result2 = Convert.ToUInt64(st2.Trim());
        }
        UInt64 num1 = Convert.ToUInt64(st.Trim());

        if (result2 == num1)
        {
            Console.WriteLine("x=y");
        }
        else if (result2 < num1)
        {
            Console.WriteLine("x<y");
        }
        else if (result2 > num1)
        {
            Console.WriteLine("x>y");
        }
    }   

Sorry to say but still 123!!! is so huge that i'm getting the same error


Traditionally m!!...! with n !s means m(m-n)(m-2n).... however here is is taken as (...((m!)!)!...)!
Note from Alec, yes I know, this is an unfortunate notation, but you see the conventional definition is far more useful (in combinatorics, the place where factorials come from) than the one the OP wants.
I would put this in a comment but it'd be eclipsed by the others and this is quite important.

like image 810
Amit Bisht Avatar asked Nov 25 '15 12:11

Amit Bisht


People also ask

How do you manually calculate factorials?

To find the factorial of a number, multiply the number with the factorial value of the previous number. For example, to know the value of 6! multiply 120 (the factorial of 5) by 6, and get 720.


2 Answers

Here, a!! is defined as (a!)!.

123!!!!!! is absolutely gigantic. I think you'd need more particles than there are in the universe if you were to write it down in ink.

You can't therefore compare the numbers directly. I conject that there is not a number class that can do this.

What you can do, is to consider the quotient 123!!!!!! / 456!!!. Many of the multiples will be similar, so you can cancel them. Note also that trailing ! will cancel. This is because x > y implies, and is implied by x! > y! where x and y are positive integers.

Eventually you'll reach a point where you can evaluate this as being less or greater than 1, so yielding your answer.

I can tell you on inspection that 123!!!!!! is larger since 123!!! is larger than 456.

like image 101
Bathsheba Avatar answered Oct 19 '22 00:10

Bathsheba


Unlike the other answers, you can do it without any approximation.

Here it is :

123 !!!!!! > 456 !!! 

means actually

123 !!!!! > 456 !!
123 !!!! > 456 ! 

and also

123 !!! > 456  

So you only need to prove the above.It's simple because you have at least one operand which can fit into an UInt64

So this should give you something like this :

public class Program
{
    static bool LeftIsGreaterThanRightSide(UInt64 leftSide, int leftSidefactCount, UInt64 rightSide)
    {
        try
        {
            checked // for the OverflowException
            {
                UInt64 input2 = leftSide;
                int factCount = leftSidefactCount;
                UInt64 result = 1;

                for (Int64 j = 0; j < factCount; j++)
                {
                    UInt64 num = input2;
                    for (UInt64 x = num; x > 0; x--)
                    {
                        result = result * x;
                    }
                }

                // None of the operand are great or equal than UInt64.MaxValue
                // So let's compare the result normaly
                return result > rightSide; 
            }
        }
        catch (OverflowException)
        {
            // leftSide overflowed, rightSide is a representable UInt64 so leftSide > rightSide ; 
            return true; 
        }
    }


    static void Main()
    {
        String input1 = Console.ReadLine();
        String input2 = Console.ReadLine();

        int fact1Count = input1.Count(c => c == '!');
        int fact2Count = input2.Count(c => c == '!');

        UInt64 x = Convert.ToUInt64(input1.Replace("!", String.Empty).Trim());
        UInt64 y = Convert.ToUInt64(input2.Replace("!", String.Empty).Trim());

        x = x == 0 ? 1 : x ; // Handling 0 !
        y = y == 0 ? 1 : y; 

        if (fact1Count > fact2Count)
        {
            fact1Count = fact1Count - fact2Count;
            Console.WriteLine(LeftIsGreaterThanRightSide(x, fact1Count, y) ? "x > y" : "x <= y");
        }
        else
        {
            fact2Count = fact2Count - fact1Count;
            Console.WriteLine(LeftIsGreaterThanRightSide(y, fact2Count, x) ? "y > x" : "y <= x");
        }

        Console.ReadLine();
    }


}
like image 22
Perfect28 Avatar answered Oct 19 '22 00:10

Perfect28