PHP构建更快的循环 - 计算混合比率

时间:2015-12-29 16:21:42

标签: php performance loops calculator blending

我想计算混合比率。三组分m1 30%,m2 30%,m3 40% 变异为5%

<?php
    $beginn = microtime(true);
    $loops = 0;
    $hits = 0;
    $precision = 1;
    $focus = 5;

    print("<table border=1 cellpadding=2>");

    for($m1 = 30 - $focus;  $m1 <= 30 + $focus; $m1 += $precision) {
    for($m2 = 30 - $focus;  $m2 <= 30 + $focus; $m2 += $precision) {
    for($m3 = 40 - $focus;  $m3 <= 40 + $focus; $m3 += $precision) {

        $loops++;

        if (($m1 + $m2 + $m3) == 100) {
            $hits++;

            print("<tr>");
            print("<td>" . $m1 . " %</td>");
            print("<td>" . $m2 . " %</td>");
            print("<td>" . $m3 . " %</td>");
            print("<td>" . ($m1 + $m2 + $m3) . " %</td>");
            print("</tr>");

        }

    }
    }
    }
    print("</table>");

    print(" Loops: " . $loops);
    print(" Hits: " . $hits);

    $dauer = microtime(true) - $beginn;
    echo " $dauer Sek.";
?>

问题是,我需要1331次循环才能找到91次点击(总计100%), 看起来像这样

&#13;
&#13;
<table border=1 cellpadding=2><tr><td>25 %</td><td>30 %</td><td>45 %</td><td>100 %</td></tr><tr><td>25 %</td><td>31 %</td><td>44 %</td><td>100 %</td></tr><tr><td>25 %</td><td>32 %</td><td>43 %</td><td>100 %</td></tr><tr><td>25 %</td><td>33 %</td><td>42 %</td><td>100 %</td></tr><tr><td>25 %</td><td>34 %</td><td>41 %</td><td>100 %</td></tr><tr><td>25 %</td><td>35 %</td><td>40 %</td><td>100 %</td></tr><tr><td>26 %</td><td>29 %</td><td>45 %</td><td>100 %</td></tr><tr><td>26 %</td><td>30 %</td><td>44 %</td><td>100 %</td></tr><tr><td>26 %</td><td>31 %</td><td>43 %</td><td>100 %</td></tr><tr><td>26 %</td><td>32 %</td><td>42 %</td><td>100 %</td></tr><tr><td>26 %</td><td>33 %</td><td>41 %</td><td>100 %</td></tr><tr><td>26 %</td><td>34 %</td><td>40 %</td><td>100 %</td></tr><tr><td>26 %</td><td>35 %</td><td>39 %</td><td>100 %</td></tr><tr><td>27 %</td><td>28 %</td><td>45 %</td><td>100 %</td></tr><tr><td>27 %</td><td>29 %</td><td>44 %</td><td>100 %</td></tr><tr><td>27 %</td><td>30 %</td><td>43 %</td><td>100 %</td></tr><tr><td>27 %</td><td>31 %</td><td>42 %</td><td>100 %</td></tr><tr><td>27 %</td><td>32 %</td><td>41 %</td><td>100 %</td></tr><tr><td>27 %</td><td>33 %</td><td>40 %</td><td>100 %</td></tr><tr><td>27 %</td><td>34 %</td><td>39 %</td><td>100 %</td></tr><tr><td>27 %</td><td>35 %</td><td>38 %</td><td>100 %</td></tr><tr><td>28 %</td><td>27 %</td><td>45 %</td><td>100 %</td></tr><tr><td>28 %</td><td>28 %</td><td>44 %</td><td>100 %</td></tr><tr><td>28 %</td><td>29 %</td><td>43 %</td><td>100 %</td></tr><tr><td>28 %</td><td>30 %</td><td>42 %</td><td>100 %</td></tr><tr><td>28 %</td><td>31 %</td><td>41 %</td><td>100 %</td></tr><tr><td>28 %</td><td>32 %</td><td>40 %</td><td>100 %</td></tr><tr><td>28 %</td><td>33 %</td><td>39 %</td><td>100 %</td></tr><tr><td>28 %</td><td>34 %</td><td>38 %</td><td>100 %</td></tr><tr><td>28 %</td><td>35 %</td><td>37 %</td><td>100 %</td></tr><tr><td>29 %</td><td>26 %</td><td>45 %</td><td>100 %</td></tr><tr><td>29 %</td><td>27 %</td><td>44 %</td><td>100 %</td></tr><tr><td>29 %</td><td>28 %</td><td>43 %</td><td>100 %</td></tr><tr><td>29 %</td><td>29 %</td><td>42 %</td><td>100 %</td></tr><tr><td>29 %</td><td>30 %</td><td>41 %</td><td>100 %</td></tr><tr><td>29 %</td><td>31 %</td><td>40 %</td><td>100 %</td></tr><tr><td>29 %</td><td>32 %</td><td>39 %</td><td>100 %</td></tr><tr><td>29 %</td><td>33 %</td><td>38 %</td><td>100 %</td></tr><tr><td>29 %</td><td>34 %</td><td>37 %</td><td>100 %</td></tr><tr><td>29 %</td><td>35 %</td><td>36 %</td><td>100 %</td></tr><tr><td>30 %</td><td>25 %</td><td>45 %</td><td>100 %</td></tr><tr><td>30 %</td><td>26 %</td><td>44 %</td><td>100 %</td></tr><tr><td>30 %</td><td>27 %</td><td>43 %</td><td>100 %</td></tr><tr><td>30 %</td><td>28 %</td><td>42 %</td><td>100 %</td></tr><tr><td>30 %</td><td>29 %</td><td>41 %</td><td>100 %</td></tr><tr><td>30 %</td><td>30 %</td><td>40 %</td><td>100 %</td></tr><tr><td>30 %</td><td>31 %</td><td>39 %</td><td>100 %</td></tr><tr><td>30 %</td><td>32 %</td><td>38 %</td><td>100 %</td></tr><tr><td>30 %</td><td>33 %</td><td>37 %</td><td>100 %</td></tr><tr><td>30 %</td><td>34 %</td><td>36 %</td><td>100 %</td></tr><tr><td>30 %</td><td>35 %</td><td>35 %</td><td>100 %</td></tr><tr><td>31 %</td><td>25 %</td><td>44 %</td><td>100 %</td></tr><tr><td>31 %</td><td>26 %</td><td>43 %</td><td>100 %</td></tr><tr><td>31 %</td><td>27 %</td><td>42 %</td><td>100 %</td></tr><tr><td>31 %</td><td>28 %</td><td>41 %</td><td>100 %</td></tr><tr><td>31 %</td><td>29 %</td><td>40 %</td><td>100 %</td></tr><tr><td>31 %</td><td>30 %</td><td>39 %</td><td>100 %</td></tr><tr><td>31 %</td><td>31 %</td><td>38 %</td><td>100 %</td></tr><tr><td>31 %</td><td>32 %</td><td>37 %</td><td>100 %</td></tr><tr><td>31 %</td><td>33 %</td><td>36 %</td><td>100 %</td></tr><tr><td>31 %</td><td>34 %</td><td>35 %</td><td>100 %</td></tr><tr><td>32 %</td><td>25 %</td><td>43 %</td><td>100 %</td></tr><tr><td>32 %</td><td>26 %</td><td>42 %</td><td>100 %</td></tr><tr><td>32 %</td><td>27 %</td><td>41 %</td><td>100 %</td></tr><tr><td>32 %</td><td>28 %</td><td>40 %</td><td>100 %</td></tr><tr><td>32 %</td><td>29 %</td><td>39 %</td><td>100 %</td></tr><tr><td>32 %</td><td>30 %</td><td>38 %</td><td>100 %</td></tr><tr><td>32 %</td><td>31 %</td><td>37 %</td><td>100 %</td></tr><tr><td>32 %</td><td>32 %</td><td>36 %</td><td>100 %</td></tr><tr><td>32 %</td><td>33 %</td><td>35 %</td><td>100 %</td></tr><tr><td>33 %</td><td>25 %</td><td>42 %</td><td>100 %</td></tr><tr><td>33 %</td><td>26 %</td><td>41 %</td><td>100 %</td></tr><tr><td>33 %</td><td>27 %</td><td>40 %</td><td>100 %</td></tr><tr><td>33 %</td><td>28 %</td><td>39 %</td><td>100 %</td></tr><tr><td>33 %</td><td>29 %</td><td>38 %</td><td>100 %</td></tr><tr><td>33 %</td><td>30 %</td><td>37 %</td><td>100 %</td></tr><tr><td>33 %</td><td>31 %</td><td>36 %</td><td>100 %</td></tr><tr><td>33 %</td><td>32 %</td><td>35 %</td><td>100 %</td></tr><tr><td>34 %</td><td>25 %</td><td>41 %</td><td>100 %</td></tr><tr><td>34 %</td><td>26 %</td><td>40 %</td><td>100 %</td></tr><tr><td>34 %</td><td>27 %</td><td>39 %</td><td>100 %</td></tr><tr><td>34 %</td><td>28 %</td><td>38 %</td><td>100 %</td></tr><tr><td>34 %</td><td>29 %</td><td>37 %</td><td>100 %</td></tr><tr><td>34 %</td><td>30 %</td><td>36 %</td><td>100 %</td></tr><tr><td>34 %</td><td>31 %</td><td>35 %</td><td>100 %</td></tr><tr><td>35 %</td><td>25 %</td><td>40 %</td><td>100 %</td></tr><tr><td>35 %</td><td>26 %</td><td>39 %</td><td>100 %</td></tr><tr><td>35 %</td><td>27 %</td><td>38 %</td><td>100 %</td></tr><tr><td>35 %</td><td>28 %</td><td>37 %</td><td>100 %</td></tr><tr><td>35 %</td><td>29 %</td><td>36 %</td><td>100 %</td></tr><tr><td>35 %</td><td>30 %</td><td>35 %</td><td>100 %</td></tr></table> 
&#13;
&#13;
&#13;

我想直接计算91次点击,所以循环将是14次 更快:))

2 个答案:

答案 0 :(得分:1)

您可以计算m2的边界,该边界将产生m3的可接受值。

例如,当m1 = 25时,由于m3的最大值为45,因此m2不能 30 30,否则25 + 29将离开46,这对于m3是不可接受的(范围35 ... 45)。

这意味着m2的下限为100 - m1 - (m3的最大值)。但这只有在这样获得的值高于m2的可接受界限时才有效:如果计算得到24而不是30,我们将不得不以m2的值25开始,因为24是不可接受的。

所以我们希望最大值(m2的最小可接受值)和(当m3位于 最大值时m2的值)。

上限的相同推理产生m2max = min(m2limit,100 - (m3min))。

$focus = 5;
$precision = 1;
$loops = 0;

for ($m1 = 30 - $focus; $m1 <= 30 + $focus; $m1 += $precision) {
    $m2a = 100 - $m1 - (40 + $focus); // This is the minimum m2 that makes sense.
    $m2a = max($m2a, 30 - $focus);  // But it must also be allowed by m2 bounds.

    $m2b = 100 - $m1 - (40 - $focus); // Maximum m2 that makes sense.
    $m2b = min($m2b, 30 + $focus); // Clip to the allowed range.

    for ($m2 = $m2a; $m2 <= $m2b; $m2 += $precision) {
        $loops++;
        $m3 = 100 - $m1 - $m2;
        print "{$m1}% + {$m2}% + {$m3}% = " . ($m1 + $m2 + $m3) . "%\n";
    }
}
print $loops . "\n";

输出:

25% + 30% + 45% = 100%
...omitted...
35% + 30% + 35% = 100%

91

要更快 - 不是有意义 - 你可以优化输出:

for ($m1 = 30 - $focus; $m1 <= 30 + $focus; $m1 += $precision) {
    $m2a = 100 - $m1 - (40 + $focus); // This is the minimum m2 that makes sense.
    $m2a = max($m2a, 30 - $focus);  // But it must also be allowed by m2 bounds.

    $m2b = 100 - $m1 - (40 - $focus); // Maximum m2 that makes sense.
    $m2b = min($m2b, 30 + $focus); // Clip to the allowed range.

    $tr = '<tr><td>' . $m1 . ' %</td><td>';

    for ($m2 = $m2a; $m2 <= $m2b; $m2 += $precision) {
        $m3 = 100 - $m1 - $m2;
        // We know that m1 + m2 + m3 = 100.
        $html .= $tr . $m2 . ' %</td><td> 100%</td></tr>';
    }
}
print $html;

答案 1 :(得分:0)

这是我想到的第一个优化......

for($m1 = 30 - $focus;  $m1 <= 30 + $focus; $m1 += $precision) {
    for($m2 = 30 - $focus;  $m2 <= 30 + $focus; $m2 += $precision) {
        $loops++;
        $m3 = 100 - $m1 - $m2;
        if ($m3>=40-$focus && $m3<=40+$focus) {
            // a hit! so print stuff
        }
    }
}

这消除了最里面的循环,$ m3,因为$ m3的必要值可以从$ m1和$ m2计算。

编辑:我刚尝试过。消除内循环会将$循环从1331减少到121.这是否接近91?任何进一步优化以接近91可能会在代码不可理解方面花费很多。