1

I have a list of numbers from the interval (0;1]. For example:

0.235
0.4
1.00
0.533
1

I need to append some new numbers to the list. To check correctness of new numbers, I need to write regex.

Firstly I write simple regex: [0|1\.]{2}\d+, but it ignores one condition: if the integer part is 1, the fractional part must contain 0 or more zeros.

So, I tried to use lookahead assertions to emulate if-else condition: (?([0\.]{2})\d+|[0]+), but it isn't working. Where is my mistake? How can I provide checking, that none of the numbers can't be more, than 1?

9
  • 4
    "To check correctness of new numbers, I need to write regex." - No, you need to convert them to a number and do a range check. Commented Jan 14, 2016 at 12:44
  • 4
    No, you don't. (Name one good reason.) Commented Jan 14, 2016 at 12:49
  • 2
    @Tomalak, ok. I'm writing a testing system. Briefly, it reads a text files and checks it using regex. All tests are regexs. Regexs stores in text files in dictionary foramat (test_name <special_delimiter> regex). So, if I start using functions, I'll need to review the architecture. Commented Jan 14, 2016 at 13:07
  • 2
    I don't believe this should be marked as duplicate, as there is a difference between (0;1] and [0;1]. I've worked it down to some regex, but as people have said, you probably don't need to use regular expressions, as using regular expressions can make code harder to read and understand. Exhibit A: (^1(\.0+)?$|^0\.(?!0+$)\d+$) That said, that should work for your case. Commented Jan 14, 2016 at 13:14
  • 1
    "So, if I start using functions, I'll need to review the architecture." You should review the architecture, because it evidently isn't good enough for what you're trying to do. If it's not this that causes you to change how you do things, it'll be something else later on, and then it'll be more work. Commented Jan 14, 2016 at 13:25

2 Answers 2

5

Better than regex is to try to convert the string to a float and check whether it is in the range:

def convert(s):
    f = float(s)
    if not 0. < f <= 1.:
        raise ValueError()
    return f

This method returns a float between 0 and 1 or it raises a ValueError (if invalid string or float not between 0 and 1)

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but I need only regular expression (of course, if it's possible) and not Python function.
one liner : return ValueError() if 0 <= s > 1 else s
@KingMak Wow, that is wrong in at least three ways.
fixed: def check(n): return n if 0 < n <= 1 else 'bad val' thanks for telling @StefanPochmann
3

So explaining my comment from above:

The Regex you Want should be:

"1 maybe followed by only 0's" OR "0 followed by a dot then some more numbers, which aren't all zeroes"

Breaking it down like this makes it easier to write.

For the first part "1 maybe followed by only 0's":

^1(\.0+)?$

This is fairly straightforward. "1" followed by (.0+) zero or one times. Where (.0+) is "." followed by one or more "0"'s.

And for the second part

^0\.(?!0+$)\d+$

This is a bit trickier. It is "0." followed by a lookahead "(?!0+$)". What this means is that if "0+$" (= "0" one or more times before the end of the string) is found it won't match. After that check you have "\d+$", which is digits, one or more times.

Combining these with an or you get:

^1(\.0+)?$|^0\.(?!0+$)\d+$

2 Comments

Without needing negative lookaheads, you could search for "0.", then "0" zero or more times, then "1-9" and finally "0-9" zero or more times. NOTE: I haven't written/tested this, but it should be easier to read/understand
New regex without negative lookaheads: ^1(\.0+)?$|^0\.0*[1-9][0-9]*$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.