Created
June 26, 2017 18:10
-
-
Save travisbrown/09e65c23044551ca9abcdc79dee6319c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def parseLong(input: CharSequence, start: Int, end: Int): Long = { | |
var negative: Boolean = false | |
var i: Int = start | |
var result: Long = 0L | |
if (input.charAt(start) == '-') { | |
negative = true | |
i += 1 | |
} | |
val limit: Long = if (negative) Long.MinValue else -Long.MaxValue | |
val limitMult: Long = limit / 10L | |
while (i < end) { | |
val digit: Int = input.charAt(i).toInt - 48 | |
if (i - start < 18) { | |
result = result * 10L - digit | |
} else { | |
if (result < limitMult) { | |
throw new NumberFormatException(s"For input string: $input") | |
} else { | |
result *= 10L | |
if (digit > 0) { | |
if (result < limit + digit) { | |
throw new NumberFormatException(s"For input string: $input") | |
} else { | |
result -= digit | |
} | |
} | |
} | |
} | |
i += 1 | |
} | |
if (negative) result else -result | |
} |
Probably wont' have an effect, but I'd be interested in seeing how moving all the "if (negative)" logic into the first branch affects performance. Like,
var limit = -Long.MaxValue
var finalMult = 1
if (input.charAt(start) == '-') {
limit = Long.MinValue
finalMult = -1L
i = 1
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Adapted (without extra testing) from an implementation I'm planning to use in circe. Note that it can be a little looser than
Long.parseLong
since the fact that we know that the input is a valid JSON number means we don't have to rule out e.g."00"
. For these benchmarks:I get these results: