0

我想用 PHP 解决一个矩阵。例如,如果我有三点:(x0, y0), (x1, y1) and (x2, y2),我想知道p[0], p[1] and p[2]中的内容y = p[2]*x^2 + p[1]*x^1 + p[0]*x^0,对所有这些点都有效。如果给出 n 分,我想解决y = p[n] * x^n + p[n-1] * x^(n-1) + ... + p[0] * x^0. 我现在所拥有的是:

<?php

$system = new EQ();
$system->add(1, 2);
$system->add(4, 5);
$system->solvePn(0);

class EQ {

    private $points = array();

    public function add($x, $y) {
        $this->points[] = array($x, $y);
    }

    public function solvePn($n) {
        // Solve p[n]
        // So eliminate p[m], p[m-1], ..., p[n+1], p[n-1], ..., p[1], p[0]
        $m = count($this->points);
        $a = $m;
        // Eliminate p[a]
        if ($a != $n) {

        }
        $a--;
    }

}
?>

但现在我不知道下一步该做什么。

4

1 回答 1

0

谢谢戴文和罗曼。我用了拉格朗日,现在效果很好。例如,如果给定 3 个点 (1,1)、(2,3)、(3,27),则该类将使用拉格朗日来计算多项式逼近。现在你可以调用 $system->f(4) 来计算这个多项式上 x=4 的 y 值。

<?php

$system = new EQ();
$system->add(1, 1);
$system->add(2, 3);
$system->add(3, 27);
echo $system->f(4);

class EQ {

    private $points = array();
    private $formula = NULL;

    public function add($x, $y) {
        $this->points[] = array($x, $y);
    }

    public function lz($z) {
        $point = $this->points[$z];
        // Get the x and y value of this point
        $x = $point[0];
        $y = $point[1];
        // Now get all points except these and build the formula
        $index = 0;
        $above = '';
        $below = 1;
        foreach ($this->points as $point) {
            if ($index != $z) {
                $xp = $point[0];
                $yp = $point[1];
                $above .= '(x-' . $xp . ')';
                $below *= ($x - $xp);
            }
            $index++;
        }
        $factor = $y / $below;
        $above = ungroup($above);
        foreach ($above as $degree=>$subfactor) {
            $above[$degree] = $subfactor * $factor;
        }
        return $above;
    }

    public function f($x) {
        if ($this->formula === NULL) $this->L();
        $formula = $this->formula;
        $val = 0;
        foreach ($formula as $degree=>$factor) {
            $subval = $factor * pow($x, $degree);
            $val += $subval;
        }
        return $val;
    }

    public function L() {
        $n = count($this->points);
        $formula = array();
        for ($z = 0; $z < $n; $z++) {
            $l = $this->lz($z);
            foreach ($l as $degree=>$factor) {
                $formula[$degree] += $factor;
            }
        }
        $this->formula = $formula;
        return $formula;
    }

}

// Transform a group-formula to a list with terms
// @example (x-1)*(x-2)
function ungroup($formula) {
    preg_match_all('/\(([^)]{1,})\)/', $formula, $matches);
    $groups = $matches[1];
    $factorTerms = getTerms(reset($groups));
    while (key($groups) < count($groups) - 1) {
        next($groups);
        $terms = getTerms(current($groups));
        $newTerms = array();
        foreach ($terms as $term) {
            foreach ($factorTerms as $factorTerm) {
                $degree = getDegree($term) + getDegree($factorTerm);
                $factor = getFactor($term) * getFactor($factorTerm);
                $newTerm = '';
                if ($factor != 1) $newTerm = ($factor == -1?'-':$factor);
                if ($degree != 0) $newTerm .= 'x' . ($degree == 1?'':'^' . $degree);
                if (strlen($newTerm) == 0) $newTerm = '0';
                $newTerms[] = $newTerm;
            }
        }
        $factorTerms = $newTerms;
    }
    $terms = array();
    foreach ($factorTerms as $term) {
        $degree = getDegree($term);
        $factor = getFactor($term);
        $terms[$degree] += $factor;
    }
    return $terms;
}

function getFactor($term) {
    if (strpos($term, 'x') !== false) {
        $pattern = '/([0-9\-]{1,})[\*]?x/';
        preg_match($pattern, $term, $matches);
        if (count($matches) == 2) {
            $n = $matches[1];
            if ($n === '-') return -1;
            return $n;
        }
        return 1;
    }
    return $term;
}

function getDegree($term) {
    if (strpos($term, 'x') !== false) {
        $pattern = '/x\^([0-9\-]{1,})/';
        preg_match($pattern, $term, $matches);
        if (count($matches) == 2) {
            return $matches[1];
        }
        return 1;
    }
    return 0;
}

function getTerms($group) {
    $group = str_replace('-', '+-', $group);
    $group = preg_replace('/\+{1,}/', '+', $group);
    $terms = explode('+', $group);
    return $terms;
}
?>
于 2011-03-29T14:00:48.860 回答