Detecting if a String is an Int
Monkey Forums/Monkey Programming/Detecting if a String is an Int
| ||
This trick to determine if a string is an Int works well with HTML5 but not with GLFW because v = 0. Is the only way for GLFW a IsNumber function that checks all characters ? (+-.0123456789) local param:String = "not_a_number" local v:Int = Int( param ) local chk:String = String(v) if chk <> "NaN" ' param is a number else ' param is a text endif |
| ||
If you ask me, it shold not work in HTML5 neither, as it is using the JavaScript NaN. In my honest opinion, to detect if a string is a number, the best way (cross platform) would be to parse its contents with a function. |
| ||
Thanks, so, here is one, is there a better way ? May be there is a string fonction that may avoid the loop ? Function IsInt:Bool( str:String ) local l:Int = str.Length() if l = 0 return false local c:Int for local n:Int = 0 until l c = str[n] if not (c = 43 or c = 45 or (c >= 48 and c <= 57)) ' - + 0 1 2 3 4 5 6 7 8 9 return false endif next return true End |
| ||
oh, it should check if + or - are only at the first position... repost later |
| ||
also the dot |
| ||
:) for IsInt ?! then: Function IsInt:Bool( str:String ) local l:Int = str.Length() if l = 0 return false local c:Int = str[0] if not (c = 43 or c = 45 or (c >= 48 and c <= 57)) ' - + 0 1 2 3 4 5 6 7 8 9 return false else if c = 43 or c = 45 if l = 1 return false ' :) we never know endif endif for local n:Int = 1 until l c = str[n] if not (c >= 48 and c <= 57) ' 0 1 2 3 4 5 6 7 8 9 return false endif next return true End Function IsFloat:Bool( str:String ) local l:Int = str.Length() if l = 0 return false local c:Int = str[0] if not (c = 43 or c = 45 or c = 46 or (c >= 48 and c <= 57)) ' - + . 0 1 2 3 4 5 6 7 8 9 return false else if c = 43 or c = 45 ' - + if l = 1 return false ' :) we never know endif endif for local n:Int = 1 until l c = str[n] if not ( c = 46 or (c >= 48 and c <= 57)) ' . 0 1 2 3 4 5 6 7 8 9 return false endif next return true End Is a dot at the last position makes a number a float ? Playing with this (my former needs are very simple as the input text can only be written from myself, it's a config text file) it makes me wonder what are all the standard ways of writing numbers... and the best (funniest?) way of checking them... |
| ||
?Method isInt(ftxt$) Return Abs(Float(ftxt))>0 Or ftxt="0" End |
| ||
ElectricBoogaloo: Explicit conversion of wrong formated strings produces a crash on java based targets such as Android, and sometimes gives a NaN on JavaScript. That's why a parser is required. (Also, being very strict, 00, -0, +0, 0.0, .0, and even . are numbers too). that's my take on it (I find it slightly simpler, but this may be just me): Function IsInt:Bool(str:String) For Local i:Int = 0 Until str.Length Local char:= str[i] 'If it's a number from 0 to 9: If char >= "0"[0] And char <= "9"[0] Continue 'Else if it's a unary operator ElseIf i = 0 And (char = "+"[0] or char = "-"[0]) And str.Length > 1 Continue 'anything else makes the str not a number. Else Return False EndIf Next Return str.Length > 0 'True, unless the string is empty End Function IsFloat:Bool(str:String) Local hasDot:Bool = False For Local i:Int = 0 Until str.Length Local char:= str[i] 'If it's a number from 0 to 9: If char >= "0"[0] And char <= "9"[0] Continue 'Else if it's a unary operator placed at the first char position ElseIf i = 0 And (char = "+"[0] or char = "-"[0]) And str.Length > 1 Continue 'else if it's a dot and there are no more dots in the string: ElseIf char = "."[0] And hasDot = False hasDot = True Continue 'anything else makes the str not a number. Else Return False EndIf Next Return str.Length > 0 'True, unless the string is empty End NOTE: Notice that things like: "+"[0]contains the integer representation of the "+" character, and this is solved at compile time by trans, so it's fast, and it avoids the creation of any arrays. Additionally, it is much more expressive in the source code than placing the constant for that specific char. So comparing something like: if char = "A"[0] Is the same as: if char = 65 But with "A"[0] you know wich character you're comparing with, while the 65 constant may be harder to follow unless the source code reader knows the mapping of chars. Also, it's not impossible to see character mapping changing in different targets, so using constants here looks a bit dangerous to me (maybe not in the US-latin area, but there are more characters and languages in the world). |
| ||
Sorry, didn't realise there were alt-target issues with that. Hmm. To be honest, I've barely touched anything user-input related, yet. Everything's been internal, so far. I should, really, start to tackle some sort of proper level editing and stuff, but .. *shrugs* I'm having fun with limits, at the minute! I you're having to scan numbers, don't forget that some countries use commas in place of decimal points. ..and then there's the times when we insert commas to split the figures up, too. You'll probably need to account for both of those scenarios. |
| ||
I you're having to scan numbers, don't forget that some countries use commas in place of decimal points. ..and then there's the times when we insert commas to split the figures up, too. You'll probably need to account for both of those scenarios. Yes, I know this. Also, those functions should ignore white space and tabs at the begining and at the end of the string, (without creating a substring to have better performance).I just wasn't going that far, but feel free to improve it and share if you want! I did have some issues with string to number conversion in an Android App, and at the end I add my own numbers only on screen keyboard, but having a realiable num-to-string conversion is a good thing. This could be a starting point? |
| ||
"+"[0] I always forget this, this is more accurate than ascii code (even if it will be the same for a long time)(but my config file is utf8) and definitely easier to read. @ElectricBougaloo that's what I meant :) but now it should be not platform dependant. @ziggy the just one dot flag is a nice find, but checking i = 0 for every char in the loop is hurting me :) (a lot, counting cycles is so far) About float representation my monkey (from its jungle) tells me: local floatvalue:Float = . Syntax error - expecting identifier. then to make your elegant function fits this constraint 'else if it's a dot and there are no more dots in the string: ElseIf char = "."[0] And hasDot = False turns to ElseIf char = "."[0] And hasDot = False And str.Length > 1 |
| ||
@ElectricBoogaloo, cross post, you're unlikely right, (and I do know this '.' / ',' issue as I'm French), (and use a lot ',' to separate values...) and the spaces and tabs... , we are then back to an ethernal question, my needs versus the "does everything" machine... I'll use the last ziggy's IsInt() |
| ||
local floatvalue:Float = Float( " +. hello nightmares... " ) ' " " are spaces and tabs (not shown here) Print floatvalue ' html5: 0 ' android: 0.0 ' glfw: 0.0 local floatvalue:Float = Float( " .42 hello nightmares... " ) ' html5: 0.42 ' android: 0.42 ' glfw (always a funny guy): 0.41999998688697815 |
| ||
but checking i = 0 for every char in the loop is hurting me If you mean logically, then maybe, but if you mean performance wise, it should not, comparing an integer is absurdly fast in all targets, and also notice that the And operator is shortcircuiting (just in case you did not know it). |
| ||
That was a joke, trying to find something not perfect in your function just for the challenge. I was refering to my old memories when, back in 1979, writing ASM code, every cycle counted. the And operator that does not execute the rest of the if line is something to know and tell. Monkey: If ObjectRef And ObjectRef.value is safe in any language. memories again: if( ptrobj && ptrobj->value ) :) (personnal thought: I wondered why I'm refering a lot to these old stuff those days, I guess it's because I'm porting PopCorn(1988, 100% ASM) to Monkey... :) ) |
| ||
That is the first time I have seen that Print "B"[0] is that in the doc's ? also makes me wonder about any other cool little short cuts that might be in there that I don't know about. |