character classes
Five possible classes: digit (0–9), sign (+/−), dot (.), exponent (e/E), or invalid. Any character outside these classes immediately rejects the string.
A financial data pipeline rejects malformed entries before parsing — strings like '+3.14', '−1e10', and '0.5E-3' must pass, while 'e', '.', and '1a' must fail. A single left-to-right scan with four boolean flags — tracking whether a digit, dot, exponent, or sign has been seen — validates the structure without backtracking or regex. O(n) time. O(1) space.
Every character belongs to exactly one category, and its legality depends on what has been seen so far.
Five possible classes: digit (0–9), sign (+/−), dot (.), exponent (e/E), or invalid. Any character outside these classes immediately rejects the string.
A sign is only legal at position 0 or directly after an exponent. A dot is rejected if one already appeared or if an exponent has started. An exponent requires that at least one digit has been seen.
Passing every character check is necessary but not sufficient. Two final conditions must hold: at least one digit was seen (hasDigit), and if an exponent appeared, at least one digit followed it (hasDigitAfterExponent).
One pass, four flags, immediate rejection on any illegal character.
Set hasDigit = false, hasDot = false, hasExponent = false, hasDigitAfterExponent = true (vacuously true — no exponent yet).
Map the current character to one of five classes: digit, sign, dot, exponent, or invalid. Invalid characters reject the string immediately.
Each class has rules. Digits always accepted — set hasDigit and possibly hasDigitAfterExponent. Signs require position 0 or post-exponent. Dots require no prior dot and no active exponent. Exponents require a prior digit and no prior exponent.
After scanning all characters: check hasDigit and hasDigitAfterExponent. Both must be true for the string to be a valid number.
Three categories of tricky inputs that test your flag logic.
".1" and "4." are both valid. A decimal point does not require digits on both sides — it only requires that at least one digit exists somewhere. Demanding digits on both sides of the dot is the classic mistake.
"1e+" is invalid even though every character is individually legal. The sign after the exponent is fine, but hasDigitAfterExponent stays false because no digit follows. The end-of-scan check catches this.
"99e2.5" is invalid. Once the exponent portion begins, the mantissa is sealed — no decimal points are allowed in the exponent. The hasExponent flag blocks the dot.