[英]Looking for a more elegant solution to this loop
I tried asking this earlier, but I don't think I phrased the question correctly so I worked out something that got me the result I was after and now am hoping that it will help someone help me. 我之前尝试过这个问题,但我认为我没有正确地提出这个问题,所以我找到了一些能让我得到结果的东西,现在我希望能帮助别人帮助我。
Problem: I have 10 items. 问题:我有10件物品。 If you buy 1, it's $10.
如果你买1,那就是10美元。 I will sell you the second one for $9.
我会以9美元的价格卖给你第二个。 I will sell you the third item for $8.
我会以8美元的价格卖给你第三件商品。 I will keep taking off money until we get to $5/item because that is the lowest I will sell it for.
我将继续取钱,直到我们达到5美元/项目,因为这是我将出售的最低价格。 So, if you buy all 10, it will cost you $65.
所以,如果你全部买10,那么你将花费65美元。
This is the pricing model I am trying to achieve, except at a much larger scale. 这是我试图实现的定价模型,除了规模要大得多。 Instead of a handful of items using dollars, I'm talking about up to millions and using fractions of pennies.
而不是使用美元的少数项目,我谈论的数百万和使用几分钱。
This is my current code: 这是我目前的代码:
<?php
function getCost($num_items)
{
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price) / ($discount_range - 1);
$price_per_unit = MAX($min_price, ($max_price - ($num_items - 1) * $discount_per_additional_item) );
return $price_per_unit;
}
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
foreach ($array as $value)
{
$sum = 0;
for ($i = 0; $i < $value; ++$i)
$sum += getCost($i);
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
Which results in: 结果如下:
100 | $1
1,000 | $7
10,000 | $70
100,000 | $675
200,000 | $1,300
300,000 | $1,875
400,000 | $2,400
500,000 | $2,875
600,000 | $3,300
700,000 | $3,675
800,000 | $4,000
900,000 | $4,275
1,000,000 | $4,500
I'm using $array as a sanity check where in the real world, I would simply calculate for the actual number the customer is being charged for. 我正在使用$ array作为一个完整性检查,在现实世界中,我只是计算客户收取的实际数量。
My question is: Is there a way to accomplish this without using a for loop? 我的问题是:有没有办法在不使用for循环的情况下完成此操作? Something, perhaps, more elegant?
或许更优雅的东西?
I made an example online: http://sandbox.onlinephpfunctions.com/code/47e270dbad8cbe16c9ea906ffd2dce098a52fbca 我在网上做了一个例子: http : //sandbox.onlinephpfunctions.com/code/47e270dbad8cbe16c9ea906ffd2dce098a52fbca
This code will have the same output, and does not have the inner loop: 此代码将具有相同的输出,并且没有内部循环:
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price)/($discount_range - 1);
$num_progressively_discounted_items =
ceil(($max_price - $min_price) / $discount_per_additional_item);
foreach ($array as $value) {
$num_items_above_min = min($value, $num_progressively_discounted_items);
$num_items_at_min = $value - $num_items_above_min;
$sum = $num_items_at_min * $min_price +
$num_items_above_min * $max_price -
$discount_per_additional_item
* $num_items_above_min * ($num_items_above_min - 1)/2;
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
This is what it does: 这就是它的作用:
0+1+2+3+4+5...+n
. 0+1+2+3+4+5...+n
的总和0+1+2+3+4+5...+n
。 For that the formula is known: n(n-1)/2
. n(n-1)/2
。 Like I mentioned in comments, there is something strange in your code: for $i=0
the value returned by getCost($i)
is higher than the max price, as the unit discount gets added to it. 就像我在评论中提到的那样,你的代码中有一些奇怪的东西:对于
$i=0
, getCost($i)
返回的值高于最高价格,因为单位折扣被添加到它。 This can be corrected by starting your inner loop with $i=1
. 这可以通过使用
$i=1
启动内部循环来纠正。 Anyway, this means there is a tiny difference in the result of my proposed code, as it does not have this peculiarity. 无论如何,这意味着我提出的代码的结果有微小的差异,因为它没有这种特性。 But as the discount per unit is so tiny, you don't actually notice it in the printed output.
但由于每单位折扣非常小,因此您在打印输出中实际上并未注意到它。
You can do this a little bit more functional style : 你可以这样做一点功能风格 :
function sumOfNaturalSeries($n)
{
return ((1 + $n) / 2) * $n;
}
$minPrice = 0.002;
$maxPrice = 0.007;
$discountRange = 1000000;
$discountStep = ($maxPrice - $minPrice) / $discountRange;
$getPrice = function ($numberOfItems) use (
$minPrice,
$maxPrice,
$discountRange,
$discountStep
) {
if ($numberOfItems <= $discountRange) {
return $maxPrice * $numberOfItems - sumOfNaturalSeries($numberOfItems - 1) * $discountStep;
}
$itemsAboveRange = $numberOfItems - $discountRange;
return $maxPrice * $discountRange - sumOfNaturalSeries($discountRange - 1) * $discountStep + $minPrice * $itemsAboveRange;
};
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
$sums = array_map($getPrice, $array);
var_dump($sums);
var_dump(array_map('number_format', $sums));
Take a notice on computational error. 注意计算错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.