I need to verify if the answer entered by a user is correct for an online quiz.
The answer is supposed to be a decimal number that may be entered in a number of different ways. For example,
0.666666...
could match
.66
.67
.66666
.667
0.6667
etc.
Basically, I want to ignore rounding, precision, and preceding zeros. The examples I found are for matching any decimal numbers.
thanks,
RT
edits -
I am writing a quiz for WebCT. It allows three options for matching correct answer: "equals", "contains" and "regular expression". I believe WebCT is Java based. But I couldn't be sure as to what flavor of regular-expression it uses. I can ask users to provide correct answer upto three decimal places. In which case correct answers could be one of the following four:
0.666
0.667
.666
.667
For a decimal representation of a fraction, you have a nice normal form: it will consist of a finite decimal, followed by a sequence of decimal digits that repeat infinitely. So, e.g., 1/7 is "0." followed by infinitely many repetitions of "142857". There's a sense (see below) in which these fractional decimal representations are the only ones that can be represented by a regular expression.
The technique for these is that you represent these with a tree, where the base part is a series of optional bracketed expressions, with alternatives to express rounding up so 8.19 would be given 8(.(2|(19?)?)?, and then repeating part starred, and then a section that gives all the ways that the repeating part may be rounded.
E.g.: 1/7 is given by 0?.(142857)*(1(4(3|2(8(6|57?)?)?)?)?)?.
Aside
The sense in which regular expressions can express only fractions is the following. Say that a formal expression describes a decimal representation if its language is all the finite decimal prefixes of the number, so an expression for 2/3 must have as its language 0, 0.6, 0.66, 0.666, &c. A finite state machine that accepts only prefixes in this way must repeat itself, and thus be a fraction.
So no regular expression accepts, say sqrt(2) exactly.
You may be better off simply converting the user-entered string into a number (using whatever language facilities you have, lke C's atof), then just ensuring it's close enough (within a set margin of error), or even by specifying a minimum and maximum (say 0.6 and 0.67).
But, if you really want a regex:
^0*\.6+7?$
should do the trick for that particular number.
That's zero of more of 0 followed by ., then one or more 6 characters and an optional 7.
To enforce at least two decimal places as requested in a comment, you could use:
^0*\.6+[67]$
That forces it to end in a 6 or 7 and have one or more 6 characters preceding that.
/^0*\.6+7?\.*$/
Broken down:
^0* <- optional zeroes
\. <- escaped decimal
6+ <- at least one 6, or more
7? <- optional 7
\.*$ <- ellipsis, at least 0 or more
It doesn't sound like you want regular expressions for this. They are purely textual and have no notion of "decimal numbers that can be expressed in more than one way."
I think what you should do is convert the user's answer to a floating-point data type in whatever programming language you're working in, and subtract it from the correct answer. The result is the error in the student's answer. If the result is less than some threshold, say +0.06, then consider it correct. That way, 0.6, 0.66, 0.667, 0.6667, etc., will all be considered correct.
Related
I trying find a regex which can satisfy my requirements for finding a set of numbers.
What is valid:
Number should be positive
All the digits should be 9
After or before decimal. Like, 9999.9999 9999 9999999999.9
9999.0000 9999.99000 is also valid because 0 after decimal doesn’t count
9999. is also valid for me
Number like 999999.8 999999998 99999990.9 99990000 is invalid because it has different number in it
The number should be greater than or equal to 9999
999.9999 99 is invalid number
Till now everything was working as expected with ^[9]{4,}\.[9]*[0]*$ this.
Later I found out, I may have exponential representation of that number.
Beauty with exponential number it will not have any trailing Zeros(0). So there is no chance of getting number like 1.1230000e5. This will be always be represented as 1.123e5.
Other conditions remains same. I wrote something like this ^[9]\.[9]{3,}[eE][0-9]*$
But this is not working on most of the cases.
Number 9.999E2(= 9.999 * 102 = 999.9) is invalid for me but the above regex says it's valid.
So found a pattern.
If the number of 9's after the decimal is N, power of exponent should be always be between 3 to N (inclusive)
9.99999eM : No of 9's after decimal 5. Here possible values of M are 3 (9999.99), 4 (99999.9) and 5 (999999). M can’t be 6 (9999990 invalid number).
Is there any way to modify this regrex ^[9]\.[9]{3,}[eE][0-9]*$ so that I can achieve my requirements?
Thanks in advance 🙏
You could adopt a "sledgehammer" approach
^[9].(([9]{3}[eE][3])|([9]{4}[eE][3-4])|([9]{5}[eE][3-5]))$
where the list of alternatives can be extended as appropriate.
Possible solutions depend on where the regex is being called. For example, if invoked from a language such as Perl or Python, would allow a programmed solution in conjunction with regex.
I'm trying to extract floating-point numbers from a string obtained from a NASTRAN solver file which has this form
CBEAM 481 3 1002 1003 0.00001.000000-4.69-14
I'm interested in the last three numbers: 0, 1, and -4.69x10^-14
I've tried multiple regex expressions up to now. I'm programming in Golang so the solution I'm looking for is in regex2. I managed to get thus far:
[-]*\d\.\d{1,4}[^\d\.]*[\+\-\d]{0,2}
The regular expression should look for the following:
A minus sign at the beginning
The first digit before the decimal
Decimal digits, more is better
Avoid a digit followed by a decimal point
Awkward scientific notation if present
My proposed solution is extracting the first digit of the next decimal number and thus is only yielding the first and third numbers.
I'm not really sure how to manage to avoid the decimal and point and also look for the scientific notation. My negated expression is not getting the job done because I'm looking for digits towards the end again!
What would the best RegEx be for allowing the input of a number below 1000000 (1 million) with 2 decimal places? For example:
Valid:
1
1.10
999999.99 (maximum)
0.50
Invalid
1.5
1.
1000000
Essentially, a currency value below 1 million.
I've come up with the following, but it requires the decimal point and doesn't require a decimal value should the decimal point be added:
^[0-9]{1,6}\\.?[0-9]{0,2}$
You can try this. ^(\d|[1-9]\d{1,5})(\.\d{2})?$ Matches any number below 1 million, with two optional decimal places. Will not match leading zeros.
https://regex101.com/r/Hz1b3G/1
If leading zeros are allowed, use this one ^0*\d{1,6}(\.\d{2})?$
I will echo the sentiment that you should check this using your programming language after the value has been entered.
A requirement like this could of course be satisfied by "1-6 digits optionally followed by a decimal point and two more digits," but in my opinion "a regular expression is not the appropriate way to do it" because soon-enough the business will come up with a twist on this requirement that will defeat this approach. When, not if, this happens, you'll regret having tried to do it this way.
Use the regex to ensure that the input IS "a number," but not to check the characteristics of that number. Use if/then/else logic elsewhere in your application for this, and all other, data-validation rules. "Less than 1 million" is simply another rule – one of many.
I got the following regex that almost does the work but does not exclude zero ...How to do that?
^(\d|\d{1,9}|1\d{1,9}|20\d{8}|213\d{7}|2146\d{6}|21473\d{5}|214747\d{4}|2147482\d{3}|21474835\d{2}|214748364[0-7])$
Also can anybody explain a bit how this works?
Regular expressions are not the right tool for this job. A much better solution is to extract the integer from your string (you can use a regex for this, just \d+), then convert that to an integer, then check the integer against your desired range.
An important corollary is to never blindly use a regular expression (or any code, really) that you don't understand yourself. What would you do if you used the regular expression above, then a requirement came in to modify the acceptable range?
As Greg said, regexes are not the right tool for the job here. But if you insist on knowing how the regex you pasted works:
The most important thing to remember is that 2**31 - 1 = 2147483647 (a number with 10 digits). In essence, the regex says:
The number can have 1-9 digits, OR
It can be 1 with any 9 digits after it, OR
20 with any 8 digits after it, OR
213 with any 7 digits after it, OR
... I'm sure you see where it's going
It restricts the numbers to the range of being below 2147483647.
P.S. given such a number as a string s, in Python, you can just pose this condition:
1 <= int(s) <= 2**31 - 1
In addition to the other answers, your regex doesn't work (besides allowing 0): it incorrectly excludes numbers like 2100000000, 2147483639, and most of the numbers between those two. The solution is to replace most of the nnnn prefixes with nnn[0-n] (along with other fixes), but the real solution is to not use regular expressions.
I am trying to match floating-point decimal numbers with a regular expression. There may or may not be a number before the decimal, and the decimal may or may not be present, and if it is present it may or may not have digits after it. (For this application, a leading +/- or a trailing "E123" is not allowed). I have written this regex:
/^([\d]*)(\.([\d]*))?$/
Which correctly matches the following:
1
1.
1.23
.23
However, this also matches empty string or a string of just a decimal point, which I do not want.
Currently I am checking after running the regex that $1 or $3 has length greater than 0. If not, it is not valid. Is there a way I can do this directly in the regex?
I think this will do what you want. It either starts with a digit, in which case the decimal point and digits after it are optional, or it starts with a decimal point, in which case at least one digit is mandatory after it.
/^\d+(\.\d*)?|\.\d+$/
Create a regular expression for each case and OR them. Then you only need test if the expression matches.
/^(\d+(\.\d*)?)|(\d*\.\d+)$/
A very late answer, but like to answer, taken from regular-expressions.info
[-+]?[\d]*\.?[\d]+?
Update This [\d]*\.?[\d]+?|[\d]+\. will help you matching 1.
http://regex101.com/r/lJ7fF4/7