Is anyone who can help me to create PHP and mysql Code. Here is the condition.
If price range is 1 to 20 USD, it will be show 2 USD.
If price range is 21 to 50 USD, it will be show 5 USD.
If price range is 51 to 100 USD, it will be show 7 USD.
how to do it with PHP or WordPress php coding.
I don't get the MySQL part here did you want to do this on the database level? or are you looking for both? anyway, in PHP it should be like this
$price = 5;
if($price >= 1 && $price <= 20){
$price = 2;
}else if($price > 20 && $price <= 50){
$price = 5;
}else if($price > 50 && $price <= 100){
$price = 7;
}
Note: you should be careful with the ranges 20.1 is greater than 20 but it is less than 21
I hope it's helpful
If you're using PHP 8, this would be elegantly done with match:
$fee = match(true) {
$price <= 20 => 2,
$price <= 50 => 5,
$price <= 100 => 7,
default => 0 // free shipping!
};
Since the evaluation ends when a "match arm" matches, we don't need to define the lower range -- as long as our ranges are defined in ascending order. I haven't used $price >= 1 && $price <= 20 => 2 for the first condition, assuming that $0.50 still costs something.
Since we're evaluating for the truth of expressions (true|false), a simple match($fee) wouldn't work. We need match(true) instead, where, when an expression evaluates as true, the corresponding value will be returned. Note that match must be exhaustive, ie. it must have a default condition if none of the conditions match (or you get an error).
On older PHP versions, the more long-winded switch can be used:
switch(true) {
case ($price >= 1 && $price <= 20):
$fee = 2;
break;
case $price <= 50:
$fee = 5;
break;
case $price <= 100:
$fee = 7;
break;
default:
$fee = 0;
break;
};
While switch doesn't require a default statement, it's a good idea to have a default value for transactions that exceed your ranges. Being nice, I give free shipping for orders > 100.
You can also of course use a series of if/elseif statements, but they become quite clunky if you have more than a small handful of conditions to check. match and switch exist to make cases like this more readable and easier to maintain.
Per #AhmedHassan's notes, your logic has a gap between 20/21, and 50/51. The next step from "less than or equal to 20" has to be "more than 20, less than or equal with 50". Or, if $20 flat already incurs the higher fee, then you should use >= 20 and < 50 for your price range boundaries.
Related
Example, I have 4 ranges:
0 - 1.25
1.26 - 2.45
2.46 - 5
5.01 - infinity
And I have a floating point number to compare with: 1.2549999999.
I need to check to what range this number belongs.
I have the following code, but I'm not convinced it's efficient enough
$comparedNumber = 1.2549999999;
if (0 < $comparedNumber && round($comparedNumber, 2) <= round(1.25,2)) {
$selectedRange = 'Range 1';
} elseif ( round(1.26,2) <= round($comparedNumber, 2) && round($comparedNumber, 2) <= round(2.45,2)) {
$selectedRange = 'Range 2';
} elseif ( round(2.46,2) <= round($comparedNumber, 2) && round($comparedNumber, 2) <= round(5,2)) {
$selectedRange = 'Range 3';
} elseif ( round(5.01,2) <= round($comparedNumber, 2) ) {
$selectedRange = 'Range 4';
} else {
$selectedRange = 'Range not exist';
}
print_r($selectedRange);
Sample here
Your problem is poorly thought out boundaries, and trying to use equality to compare floating points. Rounding is not a solution: the return value of round() is still a floating point number.
For your "ranges" you have actually three boundaries: 1.26, 2.46, and 5.01.
A generalized solution would be:
<?php
$numbers = [1.2549999999, 1.28012, 2.01212, 4.012, 5.0000012, 5.012121001, -0.12];
$boundaries = [1.26, 2.46, 5.01];
function checkRange(float $number, array $boundaries): int {
if ($number < 0) {
return -1;
}
foreach ($boundaries as $i => $boundary) {
if ($number < $boundary) {
return $i + 1;
break;
}
}
return 4;
}
foreach ($numbers as $number) {
echo "$number at Range ", checkRange($number, $boundaries), "\n";
}
/*
Output:
1.2549999999 at Range 1
1.28012 at Range 2
2.01212 at Range 2
4.012 at Range 3
5.0000012 at Range 3
5.012121001 at Range 4
-0.12 at Range -1
*/
As seen working here.
Note that the solution in the other answer fails to account for numbers in the range 4.
For this exercise, I treat numbers below 0 as "out of range", and put them in "range -1". What to do exactly with those is up to you.
This works for any given set of boundaries (as long as they are ordered), and does not need rounding at any point, since it's moot for the comparison. A number is less than the boundary, or it's not.
Your current ranges could potentially have gaps: 1.250001 would not be <= 1.25, but would not be >= 1.26 either. You've tried to handle that with round(), but the result of that is still a floating point number, and binary floating point does not accurately represent decimals. This isn't unique to PHP, it's something you'll encounter in basically every programming language (a very few have a separate type for fixed decimal numbers, trading performance for accuracy).
In particular, writing round(1.25, 2) is never going to result in a different value from writing 1.25, because the compiler will already have picked the closest floating point value to 1.25 possible.
The simple fix is to use the same boundary each time, but exclude equal values on second mention: rather than >= 1.26 in the second range, use > 1.25. However, that makes it obvious that you have redundant tests anyway, because if something doesn't fall into the <= 1.25 bucket, you already know that it is > 1.25, so don't need to test that again.
For readability (and an immeasurably tiny amount of performance), I would assign a local variable to round($comparedNumber, 2) rather than pasting it into each check. You may also decide you don't want that rounding - its effect will be to put 1.251 into the ">0, <=1.25" bucket rather than the ">1.25, <=2.45" bucket.
So it simplifies down to this:
$comparedNumber = 1.2549999999;
$roundedNumber = round($comparedNumber, 2);
if ($roundedNumber <= 0) {
$selectedRange = 'Range not exist';
} elseif ($roundedNumber <= 1.25) {
$selectedRange = 'Range 1';
} elseif ($roundedNumber <= 2.45) {
$selectedRange = 'Range 2';
} elseif ($roundedNumber <= 5) {
$selectedRange = 'Range 3';
} else {
$selectedRange = 'Range 4';
}
Since you now only need one number to define each range, making this into a loop is simple:
foreach ( $ranges as $rangeName => $rangeBoundary ) {
if ( $roundedNumber <= $rangeBoundary ) {
$selectedRange = $rangeName;
break; // stops the loop carrying on with the next test
}
}
In addition to other good answers discussing the weak idea of rounding:
Performance question too, maybe there are built in function or some trick
If the number of ranges was large, like 10+, code could efficiently determine the range via a binary search on the list of limits. With 10 limits, this would take at most 4 iterations O(log n),rather than 10 (O(n)). With 100 limits, takes at most 7.
If the ranges were approximately linearly distributed, an average range look would be O(1).
With real life distributions, a combination of the above 2 strategies is best.
With a fixed group of 4, simply test against the middle one, and then the remaining quarter.
The problem is this:
A company supplies widgets in a set of pack sizes:
250
500
1000
2000
5000
Customers can order any number of widgets, but the following rules apply:
Only whole packs can be sent and …
No more widgets than necessary should be sent and …
The fewest packs possible should be sent
Some examples showing the number of widgets ordered and the required pack quantities and sizes to correctly fulfill the order:
1 (1 x 250)
251 (1 x 500)
501 (1 x 500 and 1 x 250)
12001 (2 x 5000 and 1 x 2000 and 1 x 250)
I’ve looked at some algorithms (greedy coin change, LAFF, etc.) as these seem to provide similar solutions. However, I'm ideally looking for a scalable, object oriented approach to solving this problem.
Here's what I've come up with so far:
<?php
function countWidgets($amount)
{
$packs = array(5000, 2000, 1000, 500,
250);
$packCounter = array(0, 0, 0, 0, 0);
$packsCount = count($packs);
// loop packs
for ($i = 0; $i < $packsCount; $i++)
{
if ($amount >= $packs[$i])
{
$packCounter[$i] = intval($amount /
$packs[$i]);
$amount = $amount -
$packCounter[$i] *
$packs[$i];
}
}
// if remainder
if ($amount > 0) {
// and if smallest pack size populated
if ($packCounter[4] == 1) {
// clear smallest pack size
$packCounter[4] = 0;
// increment next biggest pack size
$packCounter[3] += 1;
} else {
// increment smallest pack size
$packCounter[4] +=1;
}
}
// Print packs
echo ("Pack ->"."\n");
for ($i = 0; $i < $packsCount; $i++)
{
if ($packCounter[$i] != 0)
{
echo ($packs[$i] . " : " .
$packCounter[$i] . "\n");
}
}
}
$amount = 251;
countWidgets($amount);
OK, I agree that this is a bit harder than I assumed yesterday. You basically have two opposing demands:
No more widgets than necessary should be sent.
The fewest packs possible should be sent.
You cannot fulfill both. So if I tried to send 1200 widgets, rule 2 says I should send a pack of 2000, however, rule 1 says I should send 2 packs: one of 1000 and one of 250. Which rule should prevail?
I chose that rule 1 should prevail in the solution below. The reason is that no customer wants more widgets than absolutely necessary.
$packSizes = [ 250,
500,
1000,
2000,
5000];
function optimizePacks($packSizes,$number)
{
rsort($packSizes);
$requiredPacks = array_fill_keys($packSizes,0);
foreach ($packSizes as $size) {
$packs = floor($number/$size);
if ($packs > 0) {
$requiredPacks[$size] = $packs;
$number -= $packs*$size;
}
}
if ($number > 0) $requiredPacks[min($packSizes)]++;
return $requiredPacks;
}
$packs = optimizePacks($packSizes,6666);
print_r($packs);
This will work for any array of pack sizes and any number of widgets. The output of this code is:
Array (
[5000] => 1
[2000] => 0
[1000] => 1
[500] => 1
[250] => 1 )
Which is one pack more than rule 2 would demand (one of 5000 and two of 1000). It would, of course, be possible to let rule 2 prevail, but I cannot fulfill both rules.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So I want to avoid typing 9999 possible outcomes doing something like this:
if($experience==50) {echo 'level 2'; }
if($experience==300) {echo 'level 3'; }
if($experience==700) {echo 'level 4'; }
if($experience==1000) {echo 'level 5'; }
Is there a way to do it? So yes i hope somebody could help me!
EDIT: The max level is 99 so i have also to check
if($level == 1 && $experience >= 50) { echo 'level 2';}
Short answer: You can't.
Long answer: You must create the experience map somewhere. In code or in a settings file/database. The system can't magical know how to map the experience to levels without you telling it how to.
What you can do however is to create a formula on how the levels are linked to experiences then it's just a small calculation and you are done.
Agreed to #Ztripez HellströmYou's answer. You need some kind of math formula, I would do something like:
$level = 1;
// level up after every 50 * $currentLevel xp gained
if ($experience >= 50 && $experience % (50*$level) == 0 && $level <= 99) {
$level++;
}
echo 'Level: ' . $level;
So above would result in the following:
$level = 1;
$experience = 50;
After if condition, $level = 2
$level = 2;
$experience = 95;
After if condition, $level = 2 //not increased
$level = 2;
$experience = 100;
After if condition, 100 % (50*2) == 0 ? true - $level = 3
etc...
Note: make sure to increase XP points by multiples of 5 so you dont go over the threshold. Or increase it by multiples of 50 or multiples of 10.
Typically, EXP-level thresholds are calculated on some kind of formula. Often this formula is exponential in nature, so you might have something like:
$base = 50;
$growth = 1.2;
$maxlevel = 100;
$levelthresholds = array();
for( $i=0; $i<$maxlevel; $i++) $levelthresholds[$i] = $base*$i*pow($growth,$i-1);
// the above is a formula I've used in many places, it works quite well
The base rate would be your EXP for Level 2, then the growth is how much you multiply the base rate by to get the next level. With 1.2, you'd get:
Level 1: 0
Level 2: 50
Level 3: 120
Level 4: 216
Level 5: 345
...
You can adapt your $base and $growth rates as desired. You can also use something like using a lower $base, rounding the result and then multiplying by 100 to get nice, rounded numbers.
The point here is to determine a formula for EXP, as this greatly reduces the amount of code you have to write. Once done you can do this:
for( $level = 0; $level < $maxlevel; $level++) {
if( $levelthresholds[$level] > $experience) break;
}
$level++; // result should be 1-based
I'm trying to make a select list of prices in my system. The prices are stored as integers. I'm able to get the lowest price and highest price but I want to display them in a select list. I don't want the select list to increment slowly but by 100 or 10,000 or, 100,000 depending on what my starting number is what where i'm at in my incrementation.
For example, say I have these 2 prices:
500000
12345689
I'm trying to increment them by 100,000 Then when I get to 1,000,000 I want to increment by that. It will look something like this:
500000
600000
700000
800000
900000
1000000
2000000
I'm using a custom function and a bit of formatting to get all my prices and get my start price and end price:
$prices = my_custom_function(); // Pulls All Prices in a random order
if(!empty($prices)){
sort($prices); // Sort Prices Lowest to Highest
$price_low = $prices[0];
$price_high = $prices[count($prices)-1];
$price_start = intval( $price_low[0].str_repeat( '0', strlen( $price_low ) - 1 ) );
$price_end = intval( ( $price_high[0] + 1 ).str_repeat( '0', strlen( $price_high ) -1 ) );
}
Using the same example above, my start price and end price will be:
$price_start = 500000
$price_end = 20000000
Now it's at the loop where I run into trouble incrementing it by the values I want. I'm trying to use a while loop and determine where I am in my incrementer:
<?php $i = $price_start; $x = 0; while($x < 10) : ?>
<option value="<?php echo $i; ?>"><?php echo format_price($i); ?></option>
<?php
if(1000 % $i == 0)
$i+=1000;
else if(10000 % $i == 0)
$i+=10000;
else if(100000 % $i == 0)
$i+=100000;
else if(1000000 % $i == 0)
$i+=1000000;
else
$i+=10000000;
$x++;
endwhile;
?>
I ended up adding in the x variable because I kept running into infinite loop problems but theoretically it should be while($i <= $price_end). Can somebody point me in the right direction on how to get the expected output please? I feel like I'm close but not quite there yet and there's probably a better / faster way to go about it. Any help would be great.
I guess a simplified way of looking at it is:
1 -> +1
10 -> +10
100 -> +100
1000 -> +1000
10000 -> +10000
and so forth.
Get power of 10: log10(1234); // 3.09131
Round down: floor(log10(1234)); // 3
Re-raise as power of 10: pow(10,floor(log10(1234))); // 1000
???
Profit.
If someone needs the full solution here it is:
$price = 100; // Starting Price
$priceEnd = 10000; // Ending Price
while($price <= $priceEnd) {
echo $price . "<br/>";
$increase = pow(10,floor(log10($price)));
$price = $price + $increase;
}
I need help with the next problem...
I have a list of values... prices in my case.
Im converting a csv file with prices. all is very good, but i need a solution to calculate a discount for a range of price.
Ex:
1234 , 230
2345, 500
5432 , 800
"modified"
i need to apply a discount of
3% off for values range 100-250
10% off for values range 250-500
25% off for values range 500-1000
so, i have the column with values.
$values[2]
$formula = round($values * 0.97, 0); // this is only geting 3% for all values from column.
But i need help to get the correct disocunt for a range all ranges.
Thanks
if ($values[2] >= 100 && $values[2] <= 250) {
$discount = 0.97;
}
else if ($values[2] > 250 && $values[2] <= 500) {
$discount = 0.9;
}
else if ($values[2] > 500 && $values[2] <= 1000) {
$discount = .75;
}
Am I missing something here?