| "The [[Float]] value of the given |
| [[string representation|string]] of a decimal floating |
| point number, or `null` if the string does not represent a |
| decimal floating point number. |
| |
| If the given string representation contains more digits |
| than can be represented by a `Float`, then the least |
| significant digits are ignored. |
| |
| The syntax accepted by this method is the same as the |
| syntax for a `Float` literal in the Ceylon language |
| except that it may optionally begin with a sign |
| character (`+` or `-`) and may not contain grouping |
| underscore characters. That is, an optional sign character, |
| followed by a string of decimal digits, followed by an |
| optional decimal point and string of decimal digits, |
| followed by an optional decimal exponent, for example |
| `e+10` or `E-5`, or SI magnitude, `k`, `M`, `G`, `T`, `P`, |
| `m`, `u`, `n`, `p`, or `f`. |
| |
| Float: Sign? Digits ('.' Digits)? (Magnitude|Exponent) |
| Sign: '+' | '-' |
| Magnitude: 'k' | 'M' | 'G' | 'T' | 'P' | 'm' | 'u' | 'n' | 'p' | 'f' |
| Exponent: ('e'|'E') Sign? Digits |
| Digits: ('0'..'9')+" |
| see (`function Float.parse`) |
| tagged("Numbers", "Basic types") |
| deprecated("Use [[Float.parse]]") |
| shared Float? parseFloat(String string) |
| => if (is Float result |
| = parseFloatInternal(string)) |
| then result |
| else null; |
| |
| class ParseFloatState |
| of start |
| | afterPlusMinus |
| | digitsBeforeDecimal |
| | afterJustDecimal |
| | afterDecimal |
| | digitsAfterDecimal |
| | afterE |
| | exponentDigits |
| | afterEPlusMinus |
| | afterSuffix |
| | invalid { |
| |
| shared new start {} |
| shared new afterPlusMinus {} |
| shared new digitsBeforeDecimal {} |
| shared new afterJustDecimal {} |
| shared new afterDecimal {} |
| shared new digitsAfterDecimal {} |
| shared new afterE {} |
| shared new exponentDigits {} |
| shared new afterEPlusMinus {} |
| shared new afterSuffix {} |
| shared new invalid {} |
| } |
| |
| Float|ParseException parseFloatInternal(String string) { |
| |
| import ceylon.language { |
| ParseFloatState { |
| start, afterPlusMinus, digitsBeforeDecimal, |
| afterJustDecimal, afterDecimal, digitsAfterDecimal, |
| afterE, exponentDigits, afterEPlusMinus, |
| afterSuffix, invalid |
| } |
| } |
| |
| |
| |
| |
| |
| variable value state = start; |
| variable value size = 0; |
| variable Integer? suffixExponent = null; |
| |
| for (ch in string) { |
| size++; |
| state = switch (state) |
| case (start) |
| if (ch == '+' || ch == '-') |
| then afterPlusMinus |
| else if ('0' <= ch <= '9') |
| then digitsBeforeDecimal |
| else if (ch == '.') |
| then afterJustDecimal |
| else invalid |
| case (afterPlusMinus) |
| if ('0' <= ch <= '9') |
| then digitsBeforeDecimal |
| else if (ch == '.') |
| then afterJustDecimal |
| else invalid |
| case (digitsBeforeDecimal) |
| if ('0' <= ch <= '9') |
| then digitsBeforeDecimal |
| else if (ch == '.') |
| then afterDecimal |
| else if (ch == 'e' || ch == 'E') |
| then afterE |
| else if (ch in "PTGMkmunpf") |
| then afterSuffix |
| else invalid |
| case (afterJustDecimal) |
| if ('0' <= ch <= '9') |
| then digitsAfterDecimal |
| else invalid |
| case (digitsAfterDecimal | |
| afterDecimal) |
| if ('0' <= ch <= '9') |
| then digitsAfterDecimal |
| else if (ch == 'e' || ch == 'E') |
| then afterE |
| else if (ch in "PTGMkmunpf") |
| then afterSuffix |
| else invalid |
| case (afterE) |
| if ('0' <= ch <= '9') |
| then exponentDigits |
| else if (ch == '+' || ch == '-') |
| then afterEPlusMinus |
| else invalid |
| case (exponentDigits | |
| afterEPlusMinus) |
| if ('0' <= ch <= '9') |
| then exponentDigits |
| else invalid |
| case (afterSuffix) |
| invalid |
| case (invalid) |
| invalid; |
| |
| if (state == afterSuffix) { |
| suffixExponent = parseSuffix(ch); |
| } |
| |
| if (state == invalid) { |
| return ParseException("illegal format for Float: unexpected character '``ch``'"); |
| } |
| } |
| |
| if (!state in [digitsBeforeDecimal, |
| afterDecimal, digitsAfterDecimal, |
| exponentDigits, afterSuffix]) { |
| return ParseException("illegal format for Float: unexpected end of string"); |
| } |
| |
| try { |
| if (exists exponent = suffixExponent) { |
| |
| return nativeParseFloat(string[0:size-1] + "E" + exponent.string); |
| } |
| else { |
| |
| return nativeParseFloat(string); |
| } |
| } |
| catch (e) { |
| return ParseException("illegal format for Float: " + e.message); |
| } |
| } |
| |
| Integer parseSuffix(Character suffix) { |
| switch (suffix) |
| case ('P') { |
| return 15; |
| } |
| case ('T') { |
| return 12; |
| } |
| case ('G') { |
| return 9; |
| } |
| case ('M') { |
| return 6; |
| } |
| case ('k') { |
| return 3; |
| } |
| case ('m') { |
| return -3; |
| } |
| case ('u') { |
| return -6; |
| } |
| case ('n') { |
| return -9; |
| } |
| case ('p') { |
| return -12; |
| } |
| case ('f') { |
| return -15; |
| } |
| else { |
| "unrecognized SI magnitude" |
| assert (false); |
| } |
| } |
| |
| native |
| Float nativeParseFloat(String string); |
| |
| native("jvm") |
| Float nativeParseFloat(String string) { |
| import java.lang { |
| Double { |
| parseDouble |
| } |
| } |
| |
| return parseDouble(string); |
| } |
| |
| native("js") |
| Float nativeParseFloat(String string) { |
| Float result; |
| dynamic { |
| result = nativeJSParseFloat(string); |
| } |
| if (result == 0.0 && string.occursAt(0, '-')) { |
| return -0.0; |
| } |
| return result; |
| } |
| |