我正在尝试编写自己的Sine函数实现以获得乐趣,但我一直在努力:
Fatal error: Maximum execution time of 30 seconds exceeded
我有一个小的HTML表单,您可以在其中输入您要查找的Sin(x)的“x”值以及要计算的“迭代次数”(值的精度),其余为PhP。 数学基于维基百科上的Sine的“系列定义”: - > http://en.wikipedia.org/wiki/Sine#Series_definition 这是我的代码:
<?php
function factorial($int) {
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
if(isset($_POST["x"]) && isset($_POST["iterations"])) {
$x = $_POST["x"];
$iterations = $_POST["iterations"];
}
else {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
if(isset($x) && is_numeric($x) && isset($iterations) && is_numeric($iterations)) {
$x = floatval($x);
$iterations = floatval($iterations);
for($i = 0; $i <= ($iterations-1); $i++) {
if($i%2 == 0) {
$operator = 1;
global $operator;
}
else {
$operator = -1;
global $operator;
}
}
for($k = 1; $k <= (($iterations-(1/2))*2); $k+2) {
$k = $k;
global $k;
}
function sinus($x, $iterations) {
if($x == 0 OR ($x%180) == 0) {
return 0;
}
else {
while($iterations != 0) {
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
$iterations = $iterations-1;
return $result;
}
}
}
$result = sinus($x, $iterations);
global $result;
}
else if(!isset($x) OR !isset($iterations)) {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
else if(isset($x) && !is_numeric($x)&& isset($iterations) && is_numeric($iterations)) {
$error = "Not a valid number.";
global $error;
}
?>
我的错误可能来自这一行的无限循环:
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
但我不知道如何解决这个问题。 我要在这一行做的是计算:
((pow($x, $k)) / (factorial($k)) + (((pow($x, $k))/(factorial($k)) * ($operator)
迭代:
+ (((pow($x, $k))/(factorial($k)) * $operator)
“$ ite”次数,“$ i”和“$ k”的值会相应变化。
我真的被困在这里了!需要一些帮助。提前谢谢!
顺便说一句:阶乘功能不是我的。我在PhP.net评论中发现它,显然它是最佳的因子函数。答案 0 :(得分:2)
为什么要计算“运算符”并在正弦函数旁边加电'k'。
sin扩展看起来像= x - x ^ 2/2! + x ^ 3/3! ....
像这样的东西。还记得迭代是整数,所以对它应用intval而不是floatval。 还在网上学习如何使用全球。无论如何,你不需要全局,因为你的'运算符'和幂'k'计算将在正弦函数内。
祝你好运。
答案 1 :(得分:1)
对于速度来说,这个阶乘函数几乎不是最优的,尽管它并不坏。至少它没有递归。虽然简单而正确。超时的主要方面是你正在调用它很多。一种用于改善其性能的技术是在本地阵列中记住先前计算的阶乘的值。或者只计算一次。
您的代码中有许多内容可以承受改进:
本声明:
while($ iterations!= 0)
如果输入$iterations
为0.1,该怎么办?或否定。这会导致无限循环。您可以使用
while ($iterations > 0)
return $result
在循环中,提前终止。这是一个经过测试的工作程序,可以针对所有这些问题进行调整:
<?php
// precompute the factorial values
global $factorials;
$factorials = array();
foreach (range (0, 170) as $j)
if ($j < 2)
$factorials [$j] = 1;
else $factorials [$j] = $factorials [$j-1] * $j;
function sinus($x, $iterations)
{
global $factorials;
$sign = 1;
for ($j = 1, $result = 0; $j < $iterations * 2; $j += 2)
{
$result += pow($x, $j) / $factorials[$j] * $sign;
$sign = - $sign;
}
return $result;
}
// test program to prove functionality
$pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620;
$x_vals = array (0, $pi/4, $pi/2, $pi, $pi * 3/2, 2 * $pi);
foreach ($x_vals as $x)
{
$y = sinus ($x, 20);
echo "sinus($x) = $y\n";
}
?>
输出:
sinus(0) = 0
sinus(0.78539816339745) = 0.70710678118655
sinus(1.5707963267949) = 1
sinus(3.1415926535898) = 3.4586691443274E-16
sinus(4.7123889803847) = -1
sinus(6.2831853071796) = 8.9457384260403E-15
顺便说一句,这很快就会执行:此输出为32毫秒。