我想计算混合比率。三组分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%), 看起来像这样
<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;
我想直接计算91次点击,所以循环将是14次 更快:))
答案 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可能会在代码不可理解方面花费很多。