tags:

views:

196

answers:

6

I'm trying to do a regular expression that'll allow numbers from 0.01 to 99.99, but not 0.0 or any null value (00.00 or 00.0 or 0.00 or 0.0) or negative value either. I've come quite close, but as usual something just isn't right. 0.0 shows as valid. Can you please help me fix this. Also, you don't need to keep the expression I've done :)

<?php
if (preg_match('/^[0-9]{1,2}[\.][0-9]{1,2}$/','0.0'))
{echo "Valid";}else{echo "Invalid";}
?>
+4  A: 

Why not

<?php
$value = '0.0';
if ($value > 0 && preg_match('/^[0-9]{1,2}[\.][0-9]{1,2}$/', $value)) {
   echo "Valid";
} else {
   echo "Invalid";
}

Sometimes a regex is not a solution, but rather a problem ;-).

Cassy
Wouldn't you want to check if the value is > 0 before you run the regex? That way if it is not there is no real reason to run the regex...
Brad F Jacobs
`'/^\d{1,2}\.\d{1,2}$/'` is equivalent but is a bit more legible.
Archimedix
@premiso: yep, you're right. Changed it accordingly.
Cassy
@Archimedix: I wanted to keep the OP's regex for emphasizing the ease of comparing with 0 :-)
Cassy
Never thought of this approach before :)
Norman
Maybe I'm not understanding PHP type conversions, but if you have a base-10 string and you convert it to floating point to check > 0, and then you convert it back to a string to check against the regexp, couldn't the float have a different string representation than the original because it got truncated (for example, 0.009999)? Or does $value remain a string the whole time?
Justin K
@Justin: the implicit casting approach would convert `'0.0'` to a floating point only for the comparison with `> 0`. It would not touch the original string. The string would always remain `'0.0'`
Cassy
This solution is probably faster, but it won't matter unless the check is inside a large loop. Although don't ever think regex is slow, it's no slower than most PHP functions.
TravisO
Also, you don't need to escape the `.` in the character set: `[.]`
gnarf
+2  A: 

Try this regular expression:

/^(?:0\.(?:0[1-9]|[1-9]\d)|[1-9]\d?\.\d\d)$/
Gumbo
Better than anything I had, but it doesn't allow leading zeros.
Kobi
@Kobi: Nobody did say anything about leading zeros. But it could be added easily: `/^0*…`
Gumbo
That seems clever. Somehow I got the notion the OP wants two digits, which made my regex messier, but you're right, it isn't specified anywhere... (maybe the list of "null values" - "00.00 or 00.0 or 0.00 or 0.0")
Kobi
This works really well after adding /^0*
Norman
This allows for only 2 digits after the decimal. Which is what i need. The rest allow more than 2.
Norman
@Norman: You should have mentioned that in the question.
Gumbo
@Gumbo : How do I adjust your solution to allow a maximum of 13 digits before the decimal? I just cant figure how you've done this. Or do i post another question?
Norman
@Norman: `/^(?:0\.(?:0[1-9]|[1-9]\d)|[1-9]\d{0,12}\.\d\d)$/`
Gumbo
+3  A: 

Are you sure you need to do it in a regular expression?

If you are using a regex because you are trying to evaluate a string, you can always cast it as a double first and then do a simple numeric comparison.

<?php 
function test_number($number)
{
    $number = (double) $number;

    if ($number >= 0.01 && $number <= 99.99) {
        return true;
    } else {
        return false;
    }
}
Joshmaker
A: 

I asume you consider only 1 or 2 digit followed by a point followed by 2 decimals

Two solutions:

1) Do a DFA than translate that to regex

   0\.0[1-9] | 0\.[1-9][0-9] | [1-9][0-9]?\.[0-9][0-9]

OR

2) accept any 1-2 digit(s), 2 decimal:

[0-9][0-9]?\.[0-9][0-9]

and then test:

 num > 0 && num < 100

:-)

Guillaume Massé
What about `0.02`…`0.09`?
Gumbo
;-) Yep you got it right
Guillaume Massé
A: 

A simple solution:

<?php

     function test($n) { 
               return($n > 0.0 and $n < 99.99);
        }

        echo test(85); //output 1(true) 
?>
The Mask
+1  A: 

Here's my attempt:

/^(?=.*[1-9])\d{0,2}(?:\.\d{0,2})?$/

First off, use a positive look-ahead ((?=.*[1-9])) to ensure that there is at least one "significant digit" in the whole mess, will fail for all forms of 0.0, 00.00 or whatever. The next part \d{0,2} allows 0, 1, or 2 digits before the decimal point, then an optional group (?:)? that includes a literal decimal, followed by 0, 1 or 2 digits: \.\d{0,2}. Use the ^ and $ to make this expression complete by only matching from beginning to end of string.

Some quick test strings:

0.0 failed.
0 failed.
12 matched.
123 failed.
05.00 matched.
0.01 matched.
gnarf