在置换方程中找到变量的值

时间:2013-05-16 12:09:46

标签: algorithm math

我有一个我无法解决的数学问题:我不知道如何找到n的值以便

365! / ((365-n)! * 365^n) = 50%.

我正在使用卡西欧500ms科学计算器,但我不知道如何。

很抱歉,因为我的问题太容易了,我正在改变自己的职业生涯,所以我必须复习和升级我的数学,这是我多年来一直忽略的主题。

3 个答案:

答案 0 :(得分:2)

理论上有一个COULD使用像牛顿方法那样的寻根方案,如果你可以采用衍生物。但是这个函数只在整数上定义,因为它使用阶乘。

一种方法是识别身份

n! = gamma(n+1)

这将有效地允许您将函数扩展到实线。伽马函数是在正实线上定义的,尽管它在负整数处确实存在奇点。当然,你仍然需要这个表达式的导数,因为伽玛是可微分的,所以可以这样做。

顺便说一下,像牛顿这样的方法对这类问题的危险是它可能仍然分散到负实线。选择较差的起始值,您可能会出现垃圾。 (我没有仔细看过这个函数的形状,所以我不会声称它会对你产生什么样的起始值。)

是否值得跳过上面的箍?当然不是。比牛顿方法更好的选择可能是布伦特算法或割线方法,这里不需要你计算导数。但即使这样也是浪费精力。

认识到这确实是整数问题,人们可以使用像二分的工具来非常有效地解决解决方案。它永远不需要衍生物,并且它在整数上可以很好地工作。一旦您将间隔解析得尽可能短,算法将终止,并在此过程中进行不同的功能评估。

最后,要小心这个功能,因为它涉及一些相当大的因子,很容易溢出许多工具来评估阶乘。例如,在MATLAB中,如果我尝试评估阶乘(365):

factorial(365)
ans =
   Inf

我得到溢出。我需要进入像符号工具箱或我自己的可变精度整数工具套件这样的工具。或者,人们可以认识到这些因子中的许多术语将被抵消,因此

365! / (365 - n)! = 365*(365-1)*(365-2)*...*(365-n+1)

关键是,如果我们不小心,我们会得到一个如此大的值的溢出。如果你有一个不会溢出的工具,那就使用它,并按照我的建议使用二分法。在这里,使用MATLAB中的符号工具箱,我得到的解决方案只使用了7个函数评估。

f = @(n) vpa(factorial(sym(365))/(factorial(sym(365 - n))*365^sym(n)));

f(0)
ans =
1.0

f(365)
ans =
1.4549552156187034033714015903853e-157

f(182)
ans =
0.00000000000000000000000095339164972764493041114884521295

f(91)
ans =
0.000004634800180846641815683109605743

f(45)
ans =
0.059024100534225072005461014516788

f(22)
ans =
0.52430469233744993108665513602619

f(23)
ans =
0.49270276567601459277458277166297

或者,如果您不能选择这样的选项,但确实有一个工具可以评估gamma函数的日志,并且您有一个rootfinder可用,就像MATLAB一样......

f = @(n) exp(gammaln(365+1) - gammaln(365-n + 1) - n*log(365));
fzero(@(n) f(n) - .5,10)
ans =
   22.7677

正如你在这里看到的,我使用了与伽马和阶乘函数相关的身份,然后在MATLAB,gammaln中使用了伽马函数的日志。一旦完成了所有肮脏的工作,我就会对整个混乱进行取样,这将是一个合理的数字。 Fzero告诉我们,交叉发生在22到23之间。

答案 1 :(得分:1)

如果数值近似值正常,请询问Wolfram Alpha

n~ = -22.2298272 ......

n~ = 22.7676903 ......

答案 2 :(得分:0)

我会假设你有一些特殊的理由需要一个实际的算法,即使你只有一个特定的问题需要解决。

你正在寻找一个值n ......

365! / ((365-n)! * 365^n) = 0.5

因此......

(365! / ((365-n)! * 365^n)) - 0.5 = 0.0

问题的一般形式是找到x的值f(x)=0。这种事情的一种经典算法是Newton-Raphson method

[编辑 - 正如木片在评论中指出的那样,因子是一个仅整数函数。我的辩护 - 对于一些问题(其中的生日问题),通常使用近似函数进行推广。我记得Stirling approximation of factorials用于生日问题 - 根据this,Knuth使用它。生日问题的Wikipedia page提到了几个推广到非整数值的近似值。

当我第一次写这个答案时,我没想到会提到这一点,这当然很糟糕。]

一个问题是你需要该功能的衍生物。这更像是一个数学问题,尽管你可以通过在任何一侧获取短距离值来估计任意点的导数。

您还可以将此视为优化问题。优化问题的一般形式是找到值x,以使f(x)最大化/最小化。在您的情况下,您可以将您的功能定义为......

f(x)=((365! / ((365-n)! * 365^n)) - 0.5)^2

由于平方,结果永远不会是负面的,所以尽量减少。无论x的{​​{1}}值是什么,您都可以获得最小的f(x)

对于整个字段而言,优化问题的算法并不多 - 您使用的方法取决于函数的复杂性。但是,只要您的语言可以应对大数字,这种情况应该很简单。可能最简单的优化算法称为hill-climbing,尽管在这种情况下它应该被称为roll-down-the-hill。幸运的是,Newton-Raphson 爬山的方法(或非常接近于一个 - 可能会有一些我不记得的小技术性。)

[ EDIT 如上所述,如果你需要实际陈述的问题的整数解(而不是实值近似),这将不起作用。整数域中的优化是有助于使优化成为字段本身的尴尬问题之一。 branch and bound对于复杂函数很常见。然而,在这种情况下,爬山仍然有效。原则上,您甚至可以使用经过调整的Newton-Raphson版本 - 您只需要进行一些舍入,并检查如果您的移动很小,则不要回到您开始的相同位置。]