Search code examples
javascalalong-integerbigintegerbigdecimal

Scala - convert large or scientific numbers to Long


Need to be able to convert 00000924843571390729101 or 2.71000000000000000E+02 to Long Expect 2.71000000000000000E+02 to become 271

funky results for this: 00000924843571390729101 became 924843571390729088
val signNumber = "00000924843571390729101"

val castnum = signNumber.toDouble.toLong.toString

First conversion below works for 2.71000000000000000E+02, 2nd one works for 00000924843571390729101

val castnum = signNumber.toDouble.toLong.toString
val castnum = signNumber.replaceAll("\\.[0-9]*$", "").toLong.toString

Do not want to keep any decimal places so not using java.math.BigDecimal

Input string may come in as 9028456928343.0000 in which case want 9028456928343 as the Long


Solution

  • The weird result in the first case is due to the fact that you are going through toDouble, limiting the precision due to how doubles are represented.

    To reliably convert from these strings to Longs you can try out BigDecimal::longValueExact as follows:

    import java.math.BigDecimal
    
    new BigDecimal("00000924843571390729101").longValueExact()
    // 924843571390729101: Long
    new BigDecimal("9028456928343.0000").longValueExact()
    // 9028456928343: Long
    new BigDecimal("2.71000000000000000E+02").longValueExact()
    // 271: Long
    

    Since you also have strings that come with decimal digits, you have to use a form of number parsing that can recognize those, even if you don't want to keep that information.

    This method will throw an ArithmeticInformation if you loose any information, meaning the number doesn't fit in a Long or it has a nonzero fractional part. If you want to be more lenient you can use BigDecimal::longValue

    import java.math.BigDecimal
    import scala.util.Try
    
    ​Try(new BigDecimal("9028456928343.0001").longValueExact())
    // Failure(java.lang.ArithmeticException: Rounding necessary): scala.util.Try
    Try(new BigDecimal("9028456928343.0001").longValue())
    // Success(9028456928343): scala.util.Try
    

    You can play around with this small snippet of code here on Scastie.