【问题标题】:Calculate from an array the number that is equal or higher and closest to a given number从数组中计算等于或大于且最接近给定数字的数字
【发布时间】:2016-04-17 20:56:01
【问题描述】:

我需要从给定的数组中计算出等于或大于 PHP 中给定数字的数字。示例:

要获取的数字:

6.85505196

要计算的数组:

3.11350000
4.38350000
4.04610000
3.99410000
2.86135817
0.50000000

只有正确的组合应该是:

3.99410000 + 2.86135817 = 6.85545817

有人可以帮助我吗?三个小时了,我要生气了!

更新:我终于完成了我的代码如下:

$arr = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
$fetch = 6.85505196;
$bestsum = get_fee($arr, $fetch);
print($bestsum);

function get_fee($arr, $fetch) {
    $bestsum = 999999999;
    $combo = array();
    $result = array();
    for ($i = 0; $i<count($arr); $i++) {
        combinations($arr, $i+1, $combo);
    }
    foreach ($combo as $idx => $arr) {
        $sum = 0;
        foreach ($arr as $value) {
            $result[$idx] += $value;
        }
        if ($result[$idx] >= $fetch && $result[$idx] < $bestsum) $bestsum = $result[$idx];
    }
    return $bestsum;
}

function combinations($arr, $level, &$combo, $curr = array()) {
    for($j = 0; $j < count($arr); $j++) {
        $new = array_merge($curr, array($arr[$j]));
        if($level == 1) {
            sort($new);
            if (!in_array($new, $combo)) {
                $combo[] = $new;          
            }
        } else {
            combinations($arr, $level - 1, $combo, $new);
        }
    }
}

【问题讨论】:

  • 能否请您发布到目前为止您尝试过的代码。 MCVE 会改善您的问题(如果没有你们自己的代码,看起来您希望我们为您编写代码)。
  • 为什么只有 3.99410000 + 2.86135817 = 6.85545817 是正确的。我看到“等于或大于给定数字”,所以上面的数组有很多合适的组合。
  • 因为 6.85545817 是最接近的组合,因为有更高的组合可能没问题,但我需要最接近的组合。实际上,我可以编写一个最接近的数字,但离我的需要还很远。
  • 你想要什么回来。两个数字?两个数字的索引?你提出的书面公式是什么?

标签: php


【解决方案1】:

我希望下面的例子可以帮助你。请试试这个

<?php
    $array = array(
            "3.11350000",
            "4.38350000",
            "4.04610000",
            "3.99410000",
            "2.86135817",
            "0.50000000"
            );

echo "<pre>";
print_r($array);// it will print your array

for($i=0; $i<count($array); $i++)
{
    $j=$i+1;

    for($j;$j<count($array); $j++)
        {
            $sum = $array[$i] + $array[$j];
            // echo $array[$i]. " + ".$array[$j]." = ".$sum."<br>"; //this will display all the combination of sum

            if($sum >= 6.85505196 && ($sum <= round(6.85505196)) )//change the condition according to your requirement
             {
              echo "The correct combinations are:<br/><br/>";
              echo "<b>". $array[$i]. " + ".$array[$j]." = ".$sum."<b>";
              echo "<br/>";
             }

        }
        echo "<br/>";

        }

    ?>

我们会得到如下结果

Array
 (
  [0] => 3.11350000
  [1] => 4.38350000
  [2] => 4.04610000
  [3] => 3.99410000
  [4] => 2.86135817
  [5] => 0.50000000
 )

The correct combinations are:

4.04610000 + 2.86135817 = 6.90745817

3.99410000 + 2.86135817 = 6.85545817

【讨论】:

  • 谢谢我已经更新并在我的代码上方添加了你的方案,它完美地处理了两个数字的组合,但是如果我的数组有超过2个数字。示例:10个数字组成的数组,正确的组合由4个数字组成,依此类推。
【解决方案2】:

你应该分两步做:

一个。制定(或查找)一个算法来完成这项工作。

b.实现它。

你没有说你在这三个小时内做了什么,所以这里有一个“蛮力”(读作:愚蠢)算法可以完成这项工作:

  1. 使用一个变量,以保持您迄今为止的最佳总和。它可以从零开始:

    $bestsum = 0;
    
  2. 尝试所有单个数字,然后是所有两个数字的总和,然后是所有三个数字的总和,等等:每次你找到一个符合你的标准并且是比当前的$bestsum 更好,将$bestsum 设置为它。还要将第二个变量$summands 设置为用于获得此结果的数字数组。 (否则你将不知道你是如何得到解决方案的)。每当您找到更好的解决方案时,请更新这两个变量。

  3. 当您尝试了每个数字组合时,您的两个变量包含最佳解决方案。打印出来。

就是这样。它保证正常工作,因为它尝试了所有可能性。有各种各样的细节需要填写,但如果遇到困难,您可以开始工作并在此处寻求特定任务的帮助。

【讨论】:

  • 我已经添加了我的实际更新代码,只是它错过了进行超过 2 种组合的部分。我想我必须做多个 foreach 但不确定,你能看看吗?谢谢。
【解决方案3】:

感谢大家的帮助! 当只需要获取一个或两个数字(加法)时,我的代码工作得非常酷。但是无法弄清楚如何将更多组合添加到给定数组中的元素总数。 我的意思是,如果我的数组中有 8 个数字,我也想尝试所有可能的组合(彼此相加)。 我的实际代码是:

    $bestsum = 1000000;
    for ($i = 0; $i < count($txinfo["vout"]); $i++) {
        if ($txinfo["vout"][$i]["value"] >= $spent && $txinfo["vout"][$i]["value"] < $bestsum) {
            $bestsum = $txinfo["vout"][$i]["value"];
        }
    }
    for($i = 0; $i < count($txinfo["vout"]); $i++) {
        $j = $i + 1;
        for($j; $j < count($txinfo["vout"]); $j++) {
            $sum = $txinfo["vout"][$i]["value"] + $txinfo["vout"][$j]["value"];
            if($sum >= $spent && $sum < $bestsum) {
                $bestsum = $sum;
            }
        }
    }
    $fee = bcsub($bestsum, $spent, 8);
    print("Fee: ".$fee);

【讨论】:

  • 不要添加额外的循环;毕竟,您不知道数组有多长,因此您不知道需要多少个循环(例如,编写 8 个嵌套循环是一个糟糕的解决方案)。把它当作一个单独的问题,写一个单独的函数来解决它:你如何得到一个数字数组的all subsets?以及如何获得子集中所有数字的总和?
  • 但是请不要使用答案来提供有关您的问题的更多信息——这违反了网站的规则。编辑您的问题以添加更多信息(但避免将整个答案放在问题中)。
  • 我很抱歉,但我不熟悉这个网站及其规则。无论如何我在这里找到了解决方案-> Find all possible unique combinations of elements of an array in PHP
  • 没问题,我们都必须学习规则。一旦你解决了你的问题,请点击旁边的大勾号“接受”对你帮助最大的答案。
【解决方案4】:

新更新的代码。

<?php
$x = 6.85505196;
$num = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
asort($num); //sort the array
$low = $num[0]; // lowest value in the array
$maxpossible = $x+$low; // this is the maximum possible answer, as we require the number that is equal or higher and closest to a given number 
$num = array_values($num);
$iterations = $x/$num[0]; // possible combinations loop, to equate to the sum of the given number using the lowest number
$sum=$num;
$newsum = $sum;
$k=count($num);
for($j=0; $j<=$iterations; $j++){   
    $l = count($sum);
    for($i=0; $i<$l; $i++){
        $genSum = $sum[$j]+$sum[$i];
        if($genSum <= $maxpossible){
            $newsum[$k] = $genSum;
            $k++;
        }
    }

    $newsum = array_unique($newsum);
    $newsum = array_values($newsum);
    $k = count($newsum);
    $sum = $newsum;
}
asort($newsum);
$newsum = array_values($newsum);
for($i=0; $i<count($newsum); $i++){
    if($x<=$newsum[$i]){
        echo "\nMaximum Possible Number = ".$newsum[$i];
        break;
    } 
}

?>

【讨论】:

  • 感谢您的帮助,但我最近完成了它。你可以在上面看到我的代码。
  • 您的脚本比我的要快,但有时无法正常工作。示例:x = 506,数组为507,8,1。问题是由“1”引起的,为什么?
  • 这到底是做什么的?为什么$iterations 设置为这个值? $maxpossible 是干什么用的?我不明白为什么 OP 接受它:当不清楚代码的用途时,无法验证代码是否正常工作。请添加算法说明。
  • 我无意点击“接受”按钮,我只是想按“有用”按钮,但按错了按钮,对不起!但是,我仍在使用自己的代码,但是一旦我使用超过 7 个以上的输入,它就不会完成循环并且无法获得正确的数字。有什么想法吗?
  • 很可能有太多的可能性;它被称为“组合爆炸”。 “优化”你的代码以减少几个周期是没有帮助的;它可能运行得更快,但会随着更大的输入大小而增长。解决它的唯一方法是查找更智能的算法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2012-12-27
  • 1970-01-01
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多