1

我正在尝试编写我自己的正弦函数实现来获得乐趣,但我不断得到:

Fatal error: Maximum execution time of 30 seconds exceeded

我有一个小的 HTML 表单,您可以在其中输入您要查找的 Sin(x) 的“x”值以及要计算的“迭代”次数(您的值的精度),其余的是 PhP。数学基于维基百科上正弦的“系列定义”:-> 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)

“$i”和“$k”的值相应改变的“$iterations”次数。

我真的被困在这里了!需要一点帮助。先感谢您 !

顺便说一句:阶乘函数不是我的。我在 PhP.net 评论中找到了它,显然它是最佳阶乘函数。

4

2 回答 2

2

你为什么要在正弦函数之外计算“运算符”和“k”功率。

sin 展开看起来像 = x - x^2/2!+ x^3/3!……

像这样的东西。

还要记住迭代是整数,所以在它上面应用 intval 而不是 floatval。也在网上学习如何使用全局。无论如何,您不需要全局,因为您的“运算符”和功率“k”计算将在正弦函数内。

祝你好运。

于 2012-04-15T02:05:59.343 回答
1

这个阶乘函数几乎不是最优的——就速度而言,虽然还不错。至少它不会递归。虽然它简单而正确。超时的主要方面是您经常调用。提高其性能的一种技术是在本地数组中记住先前计算的阶乘值。或者只计算一次。

您的代码有很多可以改进的地方:

  • 这个说法:

    而($迭代!= 0)

如果$iterations输入为 0.1 会怎样?或消极。这将导致无限循环。您可以使程序更能抵抗不良输入

while ($iterations > 0)
  • 计算正弦的公式使用奇数:1、3、5、7;不是每个整数
  • 有更简单的方法来计算交替符号。
  • 算术表达式过于复杂。
  • 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 毫秒。

于 2012-04-15T07:01:09.710 回答