比较两个因子而不计算

Co.*_*den 37 .net c# decimal factorial

有没有办法比较两个数字中哪个阶乘数更大而不计算?
场景是我正在创建ac#console应用程序,它需要两个因子输入

123!!!!!!
456!!!  
Run Code Online (Sandbox Code Playgroud)

我想要做的就是比较哪个阶乘值大于其他因素,我所做的代码片段

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();
}
Run Code Online (Sandbox Code Playgroud)

但我得到的错误是
值太大或太小十进制
我理解错误但有任何方法来做到这一点

请建议是否有任何其他数据类型可以容纳大于十进制的值,或者是否有任何其他方法来比较这些因子

实现@Bathsheba建议后,我改变了一些代码

    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");
        }
    }   
Run Code Online (Sandbox Code Playgroud)

很抱歉,但仍然是123 !!! 是如此巨大,我得到了同样的错误


传统上m!!...!n !s表示m(m-n)(m-2n)....但是这里被当作(...((m!)!)!...)!
注亚历克,是的,我知道,这是一个不幸的符号,但是你看到的传统定义是有用得多(在组合,其中阶乘来自的地方),比一个的OP想.
我会把它放在评论中,但它会被其他人黯然失色,这非常重要.

Bat*_*eba 52

在这里,a!!定义为(a!)!.

123!!!!!!绝对是巨大的.如果你用墨水写下来的话,我认为你需要更多的粒子而不是宇宙中的粒子.

因此,您无法直接比较这些数字.我认为没有一个数字类可以做到这一点.

可以做的是考虑商123!!!!!! / 456!!!.许多倍数都是相似的,所以你可以取消它们.另请注意,尾随!将取消.这是因为x> y暗示,并且暗示为x!>你!其中x和y是正整数.

最终,您将达到可以将其评估为小于或大于1的点,从而得出您的答案.

我可以告诉你,在检查123!!!!!!是更大的,因为123!!!大于456.

  • 我做了,这是一个烂摊子.陈词滥调"以面向对象的方式做"在这里适用.我通过编写一个类来表示一个整数后跟n个阶乘来解决这个问题.将每个字符串解析为它的一个实例.然后你可以构建最初的"尾随!" 琐碎的取消者.你最终得到的数字不会超过一个!在你的情况下,因为我知道123!在其扩展中包含456,它必须更大.因此,您的花哨类只需要一个解析器,一个取消器,以及与整数类型的比较. (31认同)
  • 很好的答案.一个小小的补充:有必要检查三个边界情况:0 !!! ... !!!!! = 1,1 ...... !! !!!!! = 1,2 !! ...... !!!!! = 2. (13认同)
  • "请仔细阅读我的代码","我做了,这太乱了"让我笑了.虽然很好的答案和一些非常好的建议. (11认同)
  • @AlecTeal在"具有因子能力的事物"的话语领域内,这是OP问题的背景,"!"的领域就是所有相关的.您可以将话语域扩展到所有整数或所有实数,然后抱怨"x> y <=> x!> y!`在扩大的域名上是假的是无关紧要的.你的论证类似于"驳斥"在真实的分析教科书中出现的"没有数字εstε> 0和ε²= 0"的说法"但是在双数字中有_is_这样的ε!教科书是错误的! ". (2认同)

Per*_*t28 22

与其他答案不同,您可以不做任何近似.

这里是 :

123 !!!!!! > 456 !!! 
Run Code Online (Sandbox Code Playgroud)

实际上意味着

123 !!!!! > 456 !!
123 !!!! > 456 ! 
Run Code Online (Sandbox Code Playgroud)

并且

123 !!! > 456  
Run Code Online (Sandbox Code Playgroud)

所以你只需要证明上面的内容.这很简单,因为你至少有一个可以适合的操作数 UInt64

所以这应该给你这样的东西:

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


}
Run Code Online (Sandbox Code Playgroud)

  • 有一些带有数字和整数以及阶乘数的结构,然后在它们上实现一些`operator>`比使用那个可怕的`LeftIsGreaterThanRightSide`更好.我的意思是,只是这个名字让我呕吐.不错的回答 (4认同)
  • 是的,**一旦你知道哪一个更大,就提前终止** (3认同)

Dmi*_*nko 14

对于给定的数字,假设456!!!意味着((456!)!)!我们有

  123!!!!!! == (123!!!)!!!
Run Code Online (Sandbox Code Playgroud)

  123!!! >>> 456 // >>> stands for "much, much...much larger", ">>" is not enough 
Run Code Online (Sandbox Code Playgroud)

甚至123!(1.2e205比)更大456

为了估计阶乘的实际值,让我们使用斯特林近似

https://en.wikipedia.org/wiki/Stirling%27s_approximation

  ln(n!) == n * ln(n) - n
  lg(n!) == ln(n!)/ln(10) == n * ln(n) / ln(10) - n / ln(10) == n * lg(n) - n / ln(10)
      n! == n ** n / exp(n)
Run Code Online (Sandbox Code Playgroud)

所以((456!)!)!是关于

  lg(456!)       == 1014
  lg((456!)!)    == 1e1014 * 1014- 1e1014/ln(10) == 1e1017
  lg(((456!)!)!) == 1e(1e1017) 
     ((456!)!)!  == 1e(1e(1e1017))
Run Code Online (Sandbox Code Playgroud)

这是非常庞大的数字(注意三重指数),这就是为什么不能表示为天真的BigInteger价值.

  • @black:你需要代表这个数字的位数远远超出宇宙中基本粒子的数量:) (6认同)
  • @black宇宙膨胀是宇宙粒子之间距离的增加,而不是粒子的数量;-) (6认同)

Fal*_*lco 6

这应该很简单:

正如其他人所说,你可以删除所有常见的"!" 因为x > y <==> x! > y!

您的程序基本上必须证明阶乘(123 !!!)大于普通数字.您可以通过快速退出循环来解决此问题.在计算阶乘时,您可以在产品大于456时立即返回,因为阶乘将随着额外的迭代而增长.

// While string parsing check if one number equals 0 and has at least
// one "!" - if yes set its value to 1 ( because 0! = 1! = 1 )

int x = 123;
int y = 456;
int numberOfFactorials = 3;

try
{
    for( int i = 0; i < numberOfFactorials; ++i )
    {
        for ( int j = x-1; j > 0; --j )
        {
            x *= j;
            // This quick exit will return after one iteration
            // because 123*122 > 456
            if ( x > y ) return "x is bigger than y";
        }
    }

    return x == y ? "gosh they are the same!"
                  : "x is smaller than y";
}
catch( OverflowException e )
{
   return "x Overflowed so it is bigger than y!";
}
Run Code Online (Sandbox Code Playgroud)

如果要为输入参数解析更大的数字,也可以将BigInteger与此方法一起使用.

  • 请注意,您最初给出的等价不适用于"x = 1","y = 0". (2认同)
  • @AleksiTorhamo首先删除阶乘符号,以便比较x !!!> y.y是常数,因此不会溢出.因此,如果左侧的计算溢出,您可以知道左侧大于右侧.答案并未声明您不需要处理它,它表示如果确实发生了,您就会知道答案. (2认同)