使用 PHP 求解矩阵

发布于 2024-10-28 19:02:57 字数 818 浏览 1 评论 0原文

我想用 PHP 求解矩阵。例如,如果我有三个点:(x0, y0)、(x1, y1) 和 (x2, y2),我想知道 p[0], p[1 ] 和 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--;
    }

}
?>

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

I want to solve a matrix with PHP. For example, if I have three points: (x0, y0), (x1, y1) and (x2, y2), I want to know what p[0], p[1] and p[2] is in y = p[2]*x^2 + p[1]*x^1 + p[0]*x^0, valid for all those points. If n points are given, I want to solve y = p[n] * x^n + p[n-1] * x^(n-1) + ... + p[0] * x^0. What I have at this point, is this:

<?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--;
    }

}
?>

But now I don't know what to do next.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

意犹 2024-11-04 19:02:57

谢谢达文和罗曼。我用的是拉格朗日,现在效果很好。例如,如果给定 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;
}
?>

Thanks davin and Roman. I used Lagrange for it, and it works fine now. For example, if there are 3 points given (1,1), (2,3), (3,27), the class will use Lagrange to calculate a polynomial approximation. Now you can call $system->f(4) to calculate the y-value for x=4 on this polynome.

<?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;
}
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文