Switch function in PHP - php

What do I have to write in the cases (of switch function in PHP) to make if $number > 0 && $number < 15?
I tried with:
<?php
$number = rand("0","100");
switch($number) {
case: $number > 0 && $number < 15;
$output = 1;
break;
case: $number > 15 && $number < 50;
$output = 2;
break;
}
return $output;
?>

Try the following. Your colons were in the wrong place!
<?php
$number = rand("0", "100");
switch(true) {
case $number > 0 && $number < 15:
$output = 1;
break;
case $number > 15 && $number < 50:
$output = 2;
break;
}
?>
From the comment by DaveRandom below. Be aware that nothing will happen if $number is equal to 15. I would recommend changing one of your switch statements. Perhaps by changing your first case into:
case $number > 0 && $number <= 15:

Related

converting hexadecimal to decimal php

I have to convert hexadecimal to decimal with PHP (without using hexdec) for my homework, but my code does not convert properly.
For example, when I use the function HexToDez ("1F4");, the answer should be 500, not 1.
Why is it not working?
the code
<?php
function Replace ($i)
{
switch (strToLower ($i))
{
case "a" : return 10;
case "b" : return 11;
case "c" : return 12;
case "d" : return 13;
case "e" : return 14;
case "f" : return 15;
default : return $i;
}
}
function HexToDez($i) # 1F4
{
$input=$i;
$num=strlen ($input) ;
$pos=0;
$output="";
$hochzahl="";
while($pos<$num)
{
$mid = substr ($input, $pos, 1);
$pos++;
return $end=Replace ($mid);
}
while ($end != 0){
$zahl = $input%10;
$output += $zahl*pow(16, $hochzahl);
$end = $end/10;
$hochzahl++;
}
echo $output;
}
?>
here is "classic" algorithm for you to consider, check the comments:
function HexToDez($s) {
$output = 0;
for ($i=0; $i<strlen($s); $i++) {
$c = $s[$i]; // you don't need substr to get 1 symbol from string
if ( ($c >= '0') && ($c <= '9') )
$output = $output*16 + ord($c) - ord('0'); // two things: 1. multiple by 16 2. convert digit character to integer
elseif ( ($c >= 'A') && ($c <= 'F') ) // care about upper case
$output = $output*16 + ord($s[$i]) - ord('A') + 10; // note that we're adding 10
elseif ( ($c >= 'a') && ($c <= 'f') ) // care about lower case
$output = $output*16 + ord($c) - ord('a') + 10;
}
return $output;
}
echo HexToDez("1F4"); // outputs 500
also, you can use intval function to do the same, just convert your number into hex representation, like 0x###
function HexToDez($s) {
return intval('0x'.$s, 16);
}

The switch-case failing [duplicate]

This question already has answers here:
Switch doesn't work with numeric comparison cases
(4 answers)
Closed 8 years ago.
I have a function like this:
public static function GetNilaiHuruf($nilai)
{
if($nilai > 4)
{
$nilai = (float) ((float)($nilai) / (float)(100.0) * (float)4.0);
}
switch($nilai)
{
case ($nilai > 3.66 && $nilai <= 4) :
return "A";
break;
case ($nilai > 3.33 && $nilai <= 3.66) :
return "A-";
break;
case ($nilai > 3.00 && $nilai <= 3.33) :
return 'B+';
break;
case ($nilai > 2.66 && $nilai <= 3.00) :
return 'B';
break;
case ($nilai > 2.33 && $nilai <= 2.66) :
return 'B-';
break;
case ($nilai > 2.00 && $nilai <= 2.33) :
return 'C+';
break;
case ($nilai > 1.66 && $nilai <= 2.00) :
return 'C';
break;
case ($nilai > 1.33 && $nilai <= 1.66) :
return 'C-';
break;
case ($nilai > 1.00 && $nilai <= 1.33) :
return 'D+';
break;
case ($nilai >= 0.00 && $nilai <= 1.00) :
return 'D';
break;
}
}
When I call that function with $nilai is 0, the function returns 'A';
When I call that function with $nilai is 0.007 or 'x', the function returns 'D'.
How is that possible?
That is not how switch statements work, they shouldn't be used to do numeric comparisons like that.
However, you can achieve what you want by using boolean true as your switch argument:
$yourvar = -20;
switch(true) {
case ($yourvar > 0 && $yourvar < 5) :
echo 'Hello world!';
break;
case ($yourvar < 0) :
echo 'Hello hell!';
break;
}
// Hello hell!
Please see this article for more info.
There's no need to try to use a switch here. Use if/else if/else:
if ($nilai > 3.66 && $nilai <= 4) {
return "A";
} else if ($nilai > 3.33 && $nilai <= 3.66) {
return "A-";
} ...

Returning the next nearest power of 2 for the given integer number

I want to write a function that will return next power of 2. So if input is 18 it will return 32 which is the next number greater than 18 in the series 2, 4, 8, 16, 32, 64
If input is 40 it will return 64.
Currently I am using the following function:
switch($number) {
case in_array($number, range(0, 2)):
return 2;
break;
case in_array($number, range(3, 4)):
return 4;
break;
case in_array($number, range(5, 8)):
return 8;
break;
case in_array($number, range(9, 16)):
return 16;
break;
case in_array($number, range(17, 32)):
return 32;
break;
}
Although the above works well but as you can see it is not a very elegant solution and has its limitation. Just wondering if there is a in-built PHP function or some better way of doing it.
Thanks.
Try this :
pow(2,ceil(log($number,2)))
A more effective one :
function next_pow($number)
{
if($number < 2) return 1;
for($i = 0 ; $number > 1 ; $i++)
{
$number = $number >> 1;
}
return 1<<($i+1);
}
The following code should work:
function next_power_of_two($num){
if(is_numeric($num)){
if($num > 1){
return pow(2, ceil(log($num, 2)));
}
else{
return 1;
}
}
return false;
}
$a = next_power_of_two(18); // 32
$b = next_power_of_two("377"); // 512
$c = next_power_of_two(-4); // 1
$d = next_power_of_two("water"); // false
This works well:
php > echo pow(2, (strlen(decbin(9))));
16
Convert the number to decimal, and raise 2 to the power of the number of chars.

strange beahviour with a php switch?

A sample of what I'm trying to do will be more explicit:
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case'; // This case is called !
$test = 2;
break;
default:
test = 0;
break;
}
Is there a trick here ?
thx
You cannot put comparisons inside "case" unfortunately...
A switch is only used when a value can have one of a limited number of values like so:
switch ( $val ) {
case 1:
echo "Got 1";
break;
case 2:
echo "Got 2";
break;
default:
echo "Got invalid value";
}
A workaround would be to use:
switch (true) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case';
$test = 2;
break;
default:
test = 0;
break;
}
Which will work, but is a bit ugly...
Also, you're missing a single quote in echo we are in this case'; which should be echo 'we are in this case';
You should be using an if instead =)
You need to change the switch argument to true of false if you do comparison liek that in the cases.
You are not comparing what you think you are comparing. This is the code I think you want.
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) {
$test = 0;
echo 'You are now here!';
} elseif ($opti_point >= 25 && $opti_point < 50) {
$test = 2;
} else {
test = 0;
}
In your example, you are comparing the result of the logical statement...
($opti_point>=0 && $opti_point < 25) // true
To the value of $opti_point
0 // false
So PHP is actually converting what you think in an integer into a boolean to compare it with the result of the conditional statement.
I think that's a very bad way to use a switch statement, you should not put conditional sentences in the cases... In fact, I'm sure that that would be illegal in other languages and I'm not sure that it should work in PHP. Use a number of concatenated if-else conditions instead:
if ($i == 0) {
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
I'll go true the code with you
var_dump($opti_point); //int 0 , or false --- you should use TRUE
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) { // chose the case that is $opti_point (0 or false)
case ($opti_point>= 0 && $opti_point < 25): // true, so go to next
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50): //false si this is the wan I pick
echo 'we are in this case'; // This case is called !
$test = 2;
break; // ingore the rest
default:
test = 0;
break;
}
you should use TRUE in the switch
if this is the exact code then try this
var_dump($opti_point); //int 0
if ($opti_point>=0 && $opti_point < 25) echo 'good';//echoing good
switch ($opti_point) {
case ($opti_point>= 0 && $opti_point < 25):
$test = 0;
break;
case ($opti_point >= 25 && $opti_point < 50):
echo 'we are in this case'; // This case is called !
$test = 2;
break;
default:
$test = 0;
break;
}
You have a misunderstanding on how switch-case works. Case DOES NOT TEST YOUR EXPRESSION TO BE boolean TRUE!
It compares its value to 'switch' value!
Here is an explanation:
$opti_point>= 0 && $opti_point < 25 evalutes to true which integer representation is 1 and since PHP can deal with types on it's own, it turnes true to 1 and compares it with value in switch which is 0
$opti_point >= 25 && $opti_point < 50 evaluates to false which is 0 as integer, so... that's your case ;)

Faster way to check if integer is in any of ranges?

I wonder if there is another way to shorten this ? Here is the example im looking for to do same thing just shorter.
if($c <= 100){
echo 'A';
}elseif($c <= 200 && $c > 100){
echo 'B';
}elseif($c <= 300 && $c > 200){
echo 'C';
}elseif($c <= 400 && $c > 300){
echo 'D';
}elseif($c <= 500 && $c > 400){
echo 'E';
}elseif($c <= 600 && $c > 500){
echo 'F';
}elseif($c <= 700 && $c > 600){
echo 'Z';
}elseif($c <= 800 && $c > 700){
echo 'H';
}elseif($c <= 900 && $c > 800){
echo 'I';
}elseif($c < 1000 && $c > 900){
echo 'K';
}elseif($c <= 1100 && $c > 1000){
echo 'L';
}elseif($c <= 1200 && $c > 1100){
echo 'M';
}elseif($c < 1300 && $c > 1200){
echo 'N';
}elseif($c <= 1400 && $c > 1300){
echo 'O';
}elseif($c <= 1500 && $c > 1400){
echo 'P';
}elseif($c <= 1600 && $c > 1500){
echo 'Q';
}elseif($c <= 1700 && $c > 1600){
echo 'R';
}elseif($c <= 1800 && $c > 1700){
echo 'S';
}elseif($c <= 1900 && $c > 1800){
echo 'T';
}elseif($c <= 2000 && $c > 1900){
echo 'V';
}elseif($c <= 2100 && $c > 2000){
echo 'X';
}else{
echo 'AA';
}
faster and shorter - no*, but you can make it more flexible and elegant
function find_range($n, $ranges) {
foreach($ranges as $key => $range)
if($n >= $range[0] && $n <= $range[1])
return $key;
return false;
}
$ages = array(
'baby' => array(0, 1),
'child' => array(2, 13),
'teen' => array(14, 19),
'adult' => array(20, 59),
'senior' => array(60, 100)
);
var_dump(find_range(20, $ages));
(* assuming ranges are arbitrary. If we know more about ranges, for example, that they are sorted, or always intersect, or follow some formula, we can find a better algorithm).
You could write an auxiliary function that could take an array full of anonymous functions, I guess. It would work well if your code to execute was nice and simple. Otherwise, if you're on PHP5.3 you could use proper lambdas to do more complex things. That would make it neater.
function integer_in_ranges($integer, $array) {
foreach ($array as $range => $function) {
if ($integer < $range) {
$results[] = $function();
}
}
return $results;
}
integer_in_ranges($c, array(
101 => create_function('', "execute_function(); return TRUE;"),
202 => create_function('', "execute_other_function(); return TRUE;"),
// ...
));
Not builtin, but because your plan is not that complex
switch ((int) (($c - 1) / 100)) {
case 0: /* action here */ break;
case 1: /* action here */ break;
case 2: /* action here */ break;
case 3: /* action here */ break;
default: /* action here */ break;
}
Another solution which works with arbitrary limits. I assume, that there is an upper limit
$c; // value to test
$ranges = array(101,201,199); // and so on
$index = 0;
while ($ranges[$index] >= $c) { $index++; }
// Do something useful with "$index"
Is this really your code? You always want to return AA if $c is a multiple of 100?
The fastest way to get the same result with the least amount of code would be....
$res=array('A','B','C',....);
if (($c % 100) && ($c>0) && ($c<2100)) {
echo $res[(integer)($c/100)];
} else {
echo 'AA';
}
But I would use a solution like that from sterofrog.
If the number of branches is large, you might want to look at a binary search tree
This will reduce the maximum number of comparisons that any specific branch will need to be tested against (although the minimum number of tests will also increase).
e.g. The below case there is a minimum of 2 tests and a maximum of 3 tests. In your example above, there is a maximum of 4 tests.
if ($c< 202)
{
if($c < 101){
// action 101 here
}
else {
// action 202 here
}
}
else {
if($c < 303){
// action here
}
elseif($c < 404){
// action here
}
Edit : Depends on what you mean by 'shorten'. As per your title 'faster' am assuming performance.
Edit (you've updated the List) : Case in Point 'A' needs only one comparison test, whereas the 'AA' fall through will have failed ~25 tests. Assuming an even distribution of data across all bins, the average number of tests would be ~12 ('L') whereas in a binary tree formation, the most checks would be Log2(N) + 1 - i.e. 6 tests would cover 32 branches. Unfortunately in your case, there are gaps in the data on the even '100's. If you exclude these (i.e. if value MOD 100 == 0 then fall through to 'AA') then you can do just a one sided test for the rest of the permutations.

Categories