5
$\begingroup$

I would like to test strings to see if they represent numbers. This should include number representations with precision marks and scientific notation. NumberString is unfortunately more restrictive:

mylist = {"1.23", "1.23`", "1.23*^4", "Print[fail]"}; StringMatchQ[mylist, NumberString] (* {True, False, False, False} *) 

As a complication, I want to avoid converting the strings to expressions and testing with NumberQ, as some strings may contain code which is unsafe to evaluate.

How can I make a pattern like NumberString but which matches all of the first three elements in mylist?

$\endgroup$
7
  • $\begingroup$ Are you going to self-answer? I may dig into this if not. $\endgroup$ Commented Feb 3, 2015 at 14:56
  • $\begingroup$ Also, is your reason for not converting to expressions only for safety as stated? $\endgroup$ Commented Feb 3, 2015 at 14:57
  • 1
    $\begingroup$ @Mr.Wizard, no, I'm not planning to self answer. Yes, safety is basically the only reason - it would be okay to create a held expression for example. $\endgroup$ Commented Feb 3, 2015 at 15:22
  • $\begingroup$ "I would like to test strings to see if they represent numbers." How strict are we talking here? Do you want the string "EulerGamma" to be considered a number, or are you referring to number in the sense of NumberQ? $\endgroup$ Commented Feb 3, 2015 at 19:30
  • 1
    $\begingroup$ @Mr.Wizard, the new pattern is definitely cleaner and it appears to work perfectly. Thank you. $\endgroup$ Commented Feb 12, 2015 at 19:22

3 Answers 3

4
$\begingroup$

Edit: I came to realize that my original form was redundant. I now propose this instead:

p2 = NumberString ~~ "" | "`" | ("`" | "``" ~~ NumberString) ~~ "" | ("\\*^" | "\\*^-" ~~ DigitCharacter ..); 

Test:

test = {"1.23`4.56*^-7", "1.23", "1.23`", "1.23``5", "1.23*^4", "Print[fail]"}; StringMatchQ[test, p2] 
{True, True, True, True, True, False} 
$\endgroup$
11
  • $\begingroup$ Actually you should write "\\*^", otherwise for example "1.23abc*^4" matches also True ! which is annoying for safety reasons !! $\endgroup$ Commented Feb 3, 2015 at 15:36
  • $\begingroup$ @SquareOne Right, sorry guys. $\endgroup$ Commented Feb 3, 2015 at 15:36
  • 2
    $\begingroup$ I confirm you need 2 backslashes "\\*^" not "\*^" $\endgroup$ Commented Feb 3, 2015 at 15:39
  • $\begingroup$ @SquareOne Yuck! Of course. I really made a mess of this. Thanks. I'm not sure that is the only problem however. $\endgroup$ Commented Feb 3, 2015 at 15:40
  • 1
    $\begingroup$ @Chip I think I addressed that. If you find any other problems please let me know. $\endgroup$ Commented Feb 9, 2015 at 8:16
4
$\begingroup$

RegularExpression may be helpful, like this

In[109]:= mylist = {"1.23", "1.23`", "1.23*^4", "1.22*^-2", "Print[fail]"}; numberString = RegularExpression[ "[0-9]*.?[0-9]*`?"] | (RegularExpression["[0-9]*.?[0-9]*`?"] ~~ "*^" ~~ RegularExpression["-?[0-9]+"]); StringMatchQ[mylist, numberString] Do[StringMatchQ[mylist, NumberString], {10^5}] // AbsoluteTiming Do[StringMatchQ[mylist, numberString], {10^5}] // AbsoluteTiming Out[111]= {True, True, True, True, False} Out[112]= {0.607035, Null} Out[113]= {0.917052, Null} 
$\endgroup$
1
  • $\begingroup$ See comments on Mr Wizard's answer regarding "*" acting as a wildcard $\endgroup$ Commented Feb 3, 2015 at 15:38
4
$\begingroup$

I'm not certain how general it is, but works :)

Just for fun, I've assumed that FrontEnd should know what is a number and what to split on boxes:

StringFreeQ[#, LetterCharacter] && c[#][[1, 1]] === # & /@ { "1.23", "1.23`", "1.23*^4", "Print[fail]", "string", "1`1", "1`1`1"} 
{True, True, True, False, False, True, False} 

Where c is UndocumentedTestFEParser generously introduced to us by John Fultz:

c = MathLink`CallFrontEnd[FrontEnd`UndocumentedTestFEParserPacket[#, True]] & 
$\endgroup$
2
  • $\begingroup$ This looks very interesting. My original problem came from analysing boxes so this sort of approach might fit nicely. $\endgroup$ Commented Feb 3, 2015 at 22:17
  • $\begingroup$ @SimonWoods :) great. Good luck then. $\endgroup$ Commented Feb 4, 2015 at 7:33

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.