My ASCII2Float function
After squashing my last bug, I got back to work on my current project, and the next thing was to parse my input string and return a floating point number. There was a thread somewhere that had a method for doing this, I don't have the time to dig it up atm. I modified the code to suit my needs, and went a little extra since I thought it might be useful for others. The first snippet of code is more forgiving. IE: if you feed it ' 43-2. 9.+5' it would come back with '-432.95'. The second snippet has a second parameter 'strict'. If false, it should behave like the first snippet, only slower. If 'strict' is true, however, it will return the value $7FFF_FFFF on invalid syntax, which is defined as 'NaN' in Float32. (Maybe in the IEEE specs?) A valid syntax would be an optional '+' or '-' as the first character of the string, and one optional '.' somewhere in the string. All other characters must be numeric. Spaces are not allowed either, which may mean you need to trim leading and trailing spaces before use. If anyone feels it's worth it, I'll look up the appropriate credits, and add this to the object exchange.
Both snippets require a floating point object named 'fp'. I believe any of the popular ones should work.
Tolerant code, faster than the 'strict' capable snippet.
'Strict' parameter code.
EDIT: Removed some trailing spaces that where stretching the post horizontally.
Post Edited (James Newman) : 12/10/2007 2:21:51 AM GMT
Both snippets require a floating point object named 'fp'. I believe any of the popular ones should work.
Tolerant code, faster than the 'strict' capable snippet.
PUB string2Float(address) | c, d, dp, n 'Convert an ASCII string to a float (VERY TOLERANT) d := false dp := 1 n := false repeat case c := byte[noparse][[/noparse] address++ ] "0".."9": result := result * 10 + (c - "0") if d dp := dp * 10 ".": d := true 'Could add check for already being true "-": n := true ' and if so, error, on .,-, and + signs. "+": next 0: quit 'Null byte, done parsing other: next 'Could error here result := fp.fdiv(fp.ffloat(result),fp.ffloat(dp)) if n result := fp.fneg(result)
'Strict' parameter code.
PUB string2Float(address,strict) | c, d, dp, n 'Convert an ASCII string to a float d := false dp := 1 n := false if (c := byte[noparse][[/noparse] address ]) == "-" n := true address++ elseif c == "+" address++ repeat case c := byte[noparse][[/noparse] address++ ] "0".."9": result := result * 10 + (c - "0") if d dp := dp * 10 ".": if strict ifnot d d := true else return $7FFF_FFFF 'NaN for error else d := true 0: quit 'Null byte, done parsing other: if strict return $7FFF_FFFF result := fp.fdiv(fp.ffloat(result),fp.ffloat(dp)) if n result := fp.fneg(result)
EDIT: Removed some trailing spaces that where stretching the post horizontally.
Post Edited (James Newman) : 12/10/2007 2:21:51 AM GMT
Comments
I see a minor optimization:
.. and then omitt he last two lines completely
Your optimization wouldn't work to well with the line '"0".."9": result := result * 10 + (c - "0")'. However, I could move the last two lines before the conversion to float, and make the integer value negative there. That would be faster.