patternjavaModerate
Given a String, return a boolean if it is a number
Viewed 0 times
numberbooleanreturngivenstring
Problem
Yesterday in an online interview, the interviewer asked me this question:
If I give you a string, you have to return if a string is number or
not. You are not allowed to use any parse function available.
This was my first online interview after a long long time, so I took way too much time in this question. I want to gather feedback about my solution and better ideas for the solution to this problem. You can ignore complex numbers for now.
Test cases I ran:
```
System.out.println("123 isNumber? " + isNumber("123"));
System.out.println(".123 isNumber? " + isNumber(".123"));
System.out.println("-.123 isNumber? " + isNumber("-.123"));
System.out.println("-. isNumber? " + isNumber("-."));
System.out.println(".- isNumber? " + isNumber(".-"));
System.out.println("23.34.545 isNumber? " + isNumber("23.34.545"));
System.out.println("-
If I give you a string, you have to return if a string is number or
not. You are not allowed to use any parse function available.
This was my first online interview after a long long time, so I took way too much time in this question. I want to gather feedback about my solution and better ideas for the solution to this problem. You can ignore complex numbers for now.
public static boolean isNumber(String toTest) {
boolean isNegativeFoundAlready = false;
boolean isDecimalPointFoundAlready = false;
for (int i=0; i < toTest.length(); i++) {
if (!"0123456789-.".contains(new String(new char[]{toTest.charAt(i)}))) {
return false;
} else {
if ('-' == toTest.charAt(i) && i != 0) {
return false;
}
if ('-' == toTest.charAt(i) && (i == toTest.length() - 1)) {
return false;
}
if ('-' == toTest.charAt(i) && isNegativeFoundAlready) {
return false;
}
if ('-' == toTest.charAt(i)) {
isNegativeFoundAlready = true;
}
if ('.' == toTest.charAt(i) && isDecimalPointFoundAlready) {
return false;
}
if ('.' == toTest.charAt(i)) {
isDecimalPointFoundAlready = true;
}
if ('.' == toTest.charAt(i) && (i == toTest.length() - 1)) {
return false;
}
}
}
return true;
}Test cases I ran:
```
System.out.println("123 isNumber? " + isNumber("123"));
System.out.println(".123 isNumber? " + isNumber(".123"));
System.out.println("-.123 isNumber? " + isNumber("-.123"));
System.out.println("-. isNumber? " + isNumber("-."));
System.out.println(".- isNumber? " + isNumber(".-"));
System.out.println("23.34.545 isNumber? " + isNumber("23.34.545"));
System.out.println("-
Solution
Instead of reading the output of those print statements, it's better write proper unit tests to verify your implementation:
Your implementation passes all these, which is good. I would add at least two more:
The second passes but the first doesn't and maybe it should, no?
For testing cases of non-numbers:
It would be good to split these to individual cases as I did for the valid cases. I leave that for you as an exercise. I added some more cases here too, and unfortunately the one with empty string doesn't pass. I think that's a bug.
As per your implementation, it seems more complicated than it needs to be.
Most importantly, I'm wondering if the interviewer would consider regular expressions as "parse function". If not, then the implementation can be simplified:
This passes all the above tests. To correct and simplify your implementation, it should not be terribly difficult to implement the logic of the regular expression.
@Test
public void testValidInteger() {
assertTrue(isNumber("123"));
}
@Test
public void testValidStartsWithDecimal() {
assertTrue(isNumber(".123"));
}
@Test
public void testValidNegativeStartsWithDecimal() {
assertTrue(isNumber("-.123"));
}
@Test
public void testValidDecimal() {
assertTrue(isNumber("1.23"));
}
@Test
public void testValidMinusZero() {
assertTrue(isNumber("-0"));
}Your implementation passes all these, which is good. I would add at least two more:
@Test
public void testValidEndsWithDecimal() {
assertTrue(isNumber("123."));
}
@Test
public void testValidDecimalLooooong() {
assertTrue(isNumber("1.2311111111111111111111111111111111111111111"));
}The second passes but the first doesn't and maybe it should, no?
For testing cases of non-numbers:
@Test
public void testNotValid() {
assertFalse(isNumber("-."));
assertFalse(isNumber(".-"));
assertFalse(isNumber("12.34.56"));
assertFalse(isNumber("-"));
assertFalse(isNumber("12$%^&*#"));
assertFalse(isNumber("hello"));
assertFalse(isNumber(" "));
//assertFalse(isNumber(""));
}It would be good to split these to individual cases as I did for the valid cases. I leave that for you as an exercise. I added some more cases here too, and unfortunately the one with empty string doesn't pass. I think that's a bug.
As per your implementation, it seems more complicated than it needs to be.
Most importantly, I'm wondering if the interviewer would consider regular expressions as "parse function". If not, then the implementation can be simplified:
public static boolean isNumber(String toTest) {
return toTest.matches("[+-]?(\\d*\\.?\\d+)|(\\d+\\.?\\d*)");
}This passes all the above tests. To correct and simplify your implementation, it should not be terribly difficult to implement the logic of the regular expression.
Code Snippets
@Test
public void testValidInteger() {
assertTrue(isNumber("123"));
}
@Test
public void testValidStartsWithDecimal() {
assertTrue(isNumber(".123"));
}
@Test
public void testValidNegativeStartsWithDecimal() {
assertTrue(isNumber("-.123"));
}
@Test
public void testValidDecimal() {
assertTrue(isNumber("1.23"));
}
@Test
public void testValidMinusZero() {
assertTrue(isNumber("-0"));
}@Test
public void testValidEndsWithDecimal() {
assertTrue(isNumber("123."));
}
@Test
public void testValidDecimalLooooong() {
assertTrue(isNumber("1.2311111111111111111111111111111111111111111"));
}@Test
public void testNotValid() {
assertFalse(isNumber("-."));
assertFalse(isNumber(".-"));
assertFalse(isNumber("12.34.56"));
assertFalse(isNumber("-"));
assertFalse(isNumber("12$%^&*#"));
assertFalse(isNumber("hello"));
assertFalse(isNumber(" "));
//assertFalse(isNumber(""));
}public static boolean isNumber(String toTest) {
return toTest.matches("[+-]?(\\d*\\.?\\d+)|(\\d+\\.?\\d*)");
}Context
StackExchange Code Review Q#67048, answer score: 13
Revisions (0)
No revisions yet.