Как составить регулярное выражение с плавающей точкой и ограничением?
Как составить регулярное выражение, которое пропускает число с плавающей точкой от -29999984 до 29999983?
у меня уже есть регулярное выражение, которое пропускает число с плавающей точкой:
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)
осталось лишь наложить на него ограничения
Я бы хотел видеть такое регулярное выражение, в которое я мог подставить любое минимальное число и любое максимальное
Ответы (3 шт):
Регулярные выражения воспринимают данные как строки, а не как числа, следовательно выполнять логические операции над данными они не могут. Вашу задачу правильнее и легче будет сделать с помощью if-else.
С использованием регулярных выражений такое решение сделать либо не получиться вовсе, либо оно будет очень громоздким.
Здесь есть пример ограничения от 1 до 16, но как там правильно указано данное решение не является масштабируемым.
Баловство это всё. Вот пример регулярного выражения для неотрицательных вещественных чисел с фиксированной запятой в диапазоне [0, 29999983]:
import re
def expr():
return '|'.join(f'(^{s}$)' for s in (
'[0-9]{1,7}(\.[0-9]*)?' , # s < 10000000
'1[0-9]{7}(\.[0-9]*)?' , # 10000000 <= s < 20000000
'2[0-8][0-9]{6}(\.[0-9]*)?' , # 20000000 <= s < 29000000
'29[0-8][0-9]{5}(\.[0-9]*)?' , # 29000000 <= s < 29900000
'299[0-8][0-9]{4}(\.[0-9]*)?' , # 29900000 <= s < 29990000
'2999[0-8][0-9]{3}(\.[0-9]*)?' , # 29990000 <= s < 29999000
'29999[0-8][0-9]{2}(\.[0-9]*)?' , # 29999000 <= s < 29999900
'299999[0-7][0-9](\.[0-9]*)?' , # 29999900 <= s < 29999980
'2999998[0-2](\.[0-9]*)?' , # 29999980 <= s < 29999983
'29999983(\.[0]*)?' , # 29999983 == s
))
def less(s):
return re.search(expr(), s) is not None
def test(s):
print(less(s), repr(s))
assert less(s) == (float(s) <= 29999983)
print(expr())
test('0')
test('1')
test('1.0001')
test('9999999')
test('9999999.33')
test('19999999')
test('19999999.33')
test('28999999')
test('28999999.33')
test('29899999')
test('29899999.33')
test('29989999')
test('29989999.33')
test('29998999')
test('29998999.33')
test('29999899')
test('29999899.33')
test('29999979')
test('29999979.33')
test('29999982')
test('29999982.33')
test('29999983')
test('29999983.00')
test('29999983.01')
test('29999984')
test('29999984.01')
test('29999990')
test('29999990.01')
test('30000000')
test('30000000.01')
test('99999999')
test('999999999')
Регулярка разбитая по строкам для удобства:
(^[0-9]{1,7}(\.[0-9]*)?$)| (^1[0-9]{7}(\.[0-9]*)?$)| (^2[0-8][0-9]{6}(\.[0-9]*)?$)| (^29[0-8][0-9]{5}(\.[0-9]*)?$)| (^299[0-8][0-9]{4}(\.[0-9]*)?$)| (^2999[0-8][0-9]{3}(\.[0-9]*)?$)| (^29999[0-8][0-9]{2}(\.[0-9]*)?$)| (^299999[0-7][0-9](\.[0-9]*)?$)| (^2999998[0-2](\.[0-9]*)?$)| (^29999983(\.[0]*)?$)
Регулярка:
(^[0-9]{1,7}(\.[0-9]*)?$)|(^1[0-9]{7}(\.[0-9]*)?$)|(^2[0-8][0-9]{6}(\.[0-9]*)?$)|(^29[0-8][0-9]{5}(\.[0-9]*)?$)|(^299[0-8][0-9]{4}(\.[0-9]*)?$)|(^2999[0-8][0-9]{3}(\.[0-9]*)?$)|(^29999[0-8][0-9]{2}(\.[0-9]*)?$)|(^299999[0-7][0-9](\.[0-9]*)?$)|(^2999998[0-2](\.[0-9]*)?$)|(^29999983(\.[0]*)?$)
Отрицательный диапазон строится по аналогии. Нетрудно написать автоматический генератор.
Stanislav Volodarskiy Дал правильное решение.
только чтобы учесть весь диапазон, нужно расширить это
def expr():
return '|'.join(f'(^{s}$)' for s in (
'[0-9]{1,7}(\.[0-9]*)?' , # s < 10000000
'1[0-9]{7}(\.[0-9]*)?' , # 10000000 <= s < 20000000
'2[0-8][0-9]{6}(\.[0-9]*)?' , # 20000000 <= s < 29000000
'29[0-8][0-9]{5}(\.[0-9]*)?' , # 29000000 <= s < 29900000
'299[0-8][0-9]{4}(\.[0-9]*)?' , # 29900000 <= s < 29990000
'2999[0-8][0-9]{3}(\.[0-9]*)?' , # 29990000 <= s < 29999000
'29999[0-8][0-9]{2}(\.[0-9]*)?' , # 29999000 <= s < 29999900
'299999[0-7][0-9](\.[0-9]*)?' , # 29999900 <= s < 29999980
'2999998[0-2](\.[0-9]*)?' , # 29999980 <= s < 29999983
'29999983(\.[0]*)?' , # 29999983 == s
))
на это:
def expr():
return '|'.join(f'(^{s}$)' for s in (
'-[0-9]{1,7}(\.[0-9]*)?'
'-1[0-9]{7}(\.[0-9]*)?',
'-2[0-8][0-9]{6}(\.[0-9]*)?',
'-29[0-8][0-9]{5}(\.[0-9]*)?',
'-299[0-8][0-9]{4}(\.[0-9]*)?',
'-2999[0-8][0-9]{3}(\.[0-9]*)?',
'-29999[0-8][0-9]{2}(\.[0-9]*)?',
'-299999[0-7][0-9](\.[0-9]*)?',
'-2999998[0-3](\.[0-9]*)?',
'-29999984(\.[0]*)?',
'[0-9]{1,7}(\.[0-9]*)?' , # s < 10000000
'1[0-9]{7}(\.[0-9]*)?' , # 10000000 <= s < 20000000
'2[0-8][0-9]{6}(\.[0-9]*)?' , # 20000000 <= s < 29000000
'29[0-8][0-9]{5}(\.[0-9]*)?' , # 29000000 <= s < 29900000
'299[0-8][0-9]{4}(\.[0-9]*)?' , # 29900000 <= s < 29990000
'2999[0-8][0-9]{3}(\.[0-9]*)?' , # 29990000 <= s < 29999000
'29999[0-8][0-9]{2}(\.[0-9]*)?' , # 29999000 <= s < 29999900
'299999[0-7][0-9](\.[0-9]*)?' , # 29999900 <= s < 29999980
'2999998[0-2](\.[0-9]*)?' , # 29999980 <= s < 29999983
'29999983(\.[0]*)?' , # 29999983 == s
))
и конечное регулярное выражение будет следующим:
(^-1[0-9]{7}(\.[0-9]*)?$)|(^-2[0-8][0-9]{6}(\.[0-9]*)?$)|(^-29[0-8][0-9]{5}(\.[0-9]*)?$)|(^-299[0-8][0-9]{4}(\.[0-9]*)?$)|(^-2999[0-8][0-9]{3}(\.[0-9]*)?$)|(^-29999[0-8][0-9]{2}(\.[0-9]*)?$)|(^-299999[0-7][0-9](\.[0-9]*)?$)|(^-2999998[0-3](\.[0-9]*)?$)|(^-29999984(\.[0]*)?$)|(^[0-9]{1,7}(\.[0-9]*)?$)|(^1[0-9]{7}(\.[0-9]*)?$)|(^2[0-8][0-9]{6}(\.[0-9]*)?$)|(^29[0-8][0-9]{5}(\.[0-9]*)?$)|(^299[0-8][0-9]{4}(\.[0-9]*)?$)|(^2999[0-8][0-9]{3}(\.[0-9]*)?$)|(^29999[0-8][0-9]{2}(\.[0-9]*)?$)|(^299999[0-7][0-9](\.[0-9]*)?$)|(^2999998[0-2](\.[0-9]*)?$)|(^29999983(\.[0]*)?$)
Также, предлагаю регулярное выражение с тем же функционалом, но сокращенной записью
def expr():
return '|'.join(f'(^{s}$)' for s in (
'[+-]?[0-9]{1,7}(\.[0-9]*)?|\.[0-9]+',
'[+-]?1[0-9]{7}(\.[0-9]*)?',
'[+-]?2[0-8][0-9]{6}(\.[0-9]*)?',
'[+-]?29[0-8][0-9]{5}(\.[0-9]*)?',
'[+-]?299[0-8][0-9]{4}(\.[0-9]*)?',
'[+-]?2999[0-8][0-9]{3}(\.[0-9]*)?',
'[+-]?29999[0-8][0-9]{2}(\.[0-9]*)?',
'[+-]?299999[0-7][0-9](\.[0-9]*)?',
'\-2999998[0-3](\.[0-9]*)?',
'[+]?2999998[0-2](\.[0-9]*)?',
'\-29999984(\.[0]*)?',
'29999983(\.[0]*)?',
))
и конечное регулярное выражение будет следующим:
(^[+-]?[0-9]{1,7}(\.[0-9]*)?|\.[0-9]+$)|(^[+-]?1[0-9]{7}(\.[0-9]*)?$)|(^[+-]?2[0-8][0-9]{6}(\.[0-9]*)?$)|(^[+-]?29[0-8][0-9]{5}(\.[0-9]*)?$)|(^[+-]?299[0-8][0-9]{4}(\.[0-9]*)?$)|(^[+-]?2999[0-8][0-9]{3}(\.[0-9]*)?$)|(^[+-]?29999[0-8][0-9]{2}(\.[0-9]*)?$)|(^[+-]?299999[0-7][0-9](\.[0-9]*)?$)|(^\-2999998[0-3](\.[0-9]*)?$)|(^[+]?2999998[0-2](\.[0-9]*)?$)|(^\-29999984(\.[0]*)?$)|(^29999983(\.[0]*)?$)