Reputation: 2916
I thought this would be extremely simple but it turns out in PHP it's tricky to determine whether a string contains only an integer or a float which is a whole or half number.
For example, I want:
// Approved
"0.5"
"12"
"22.5"
"6.0"
"1"
"0"
// Rejected
"0.65"
"foo19bar"
"ten"
"39.4"
"s12"
"0x600"
Things making it tricky:
Detecting (only) floats in strings is hard:
is_float()
rejects strings, obviously (e.g. is_float("2.5") = false
)is_float((float)"wat2.5") = true
)Detecting if a float is whole or half is also weird:
%
) automatically casts to int
for some reason so you need to use fmod()
instead (e.g. 10.33 % 0.5
returns 0
in PHP 5.4)My most succinct solution so far is this one, but I feel like there should be a better way to do this:
if (ctype_digit($rating) || (is_float($rating + 0) && fmod($rating, 0.5) == 0)) {
if (is_numeric($rating)) {
echo "Approved";
}
}
Upvotes: 2
Views: 262
Reputation: 27864
<?php
$test = [
"0.5",
"12",
"22.5",
"6.0",
"1",
"0",
"0.65",
"foo19bar",
"ten",
"39.4",
"s12",
"0x600",
];
foreach ($test as $number)
if ((string)((int)((double)$number * 2) / 2) == $number)
echo "Approved $number\n";
else
echo "Rejected $number\n";
Outputs:
Approved 0.5
Approved 12
Approved 22.5
Approved 6.0
Approved 1
Approved 0
Rejected 0.65
Rejected foo19bar
Rejected ten
Rejected 39.4
Rejected s12
Rejected 0x600
Upvotes: 4
Reputation: 147166
Why not just use a regex e.g.
if (preg_match('/^\d+(\.[05]0*)?$/', $rating)) echo "\"$rating\": Approved\n";
This one will allow trailing 0s after a number so 4.50 will pass as does 4.5. If you don't want that just remove the 0*
part of it.
e.g.
$ratings = array(
"0.5",
"12" ,
"22.5" ,
"6.0",
"1",
"0",
"4.5",
"3.500",
"1.00",
"0.65" ,
"foo19bar" ,
"ten" ,
"39.4",
"s12",
"0x600"
);
foreach ($ratings as $rating) {
echo "\"$rating\": " . (preg_match('/^\d+(\.[05]0*)?$/', $rating) ? "Approved\n" : "Rejected\n");
}
Output:
"0.5": Approved
"12": Approved
"22.5": Approved
"6.0": Approved
"1": Approved
"0": Approved
"4.5": Approved
"3.500": Approved
"1.00": Approved
"0.65": Rejected
"foo19bar": Rejected
"ten": Rejected
"39.4": Rejected
"s12": Rejected
"0x600": Rejected
Upvotes: 2