Scala - конвертировать большие или научные числа в длинные

Необходимо иметь возможность конвертировать 00000924843571390729101 или 2.71000000000000000E+02 в Long Expect 2.710000000000000000E+02, чтобы получить 271

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

val castnum = signNumber.toDouble.toLong.toString

Первое преобразование ниже работает для 2.710000000000000000E+02, второе работает для 00000924843571390729101

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

Не хотите сохранять десятичные знаки, поэтому не используйте java.math.BigDecimal

Входная строка может иметь вид 9028456928343.0000, и в этом случае нужно 9028456928343 в качестве длинного


person tooptoop4    schedule 21.06.2018    source источник


Ответы (1)


Странный результат в первом случае связан с тем, что вы проходите через toDouble, ограничивая точность из-за того, как представлены двойные числа.

Чтобы надежно преобразовать эти строки в Longs, вы можете попробовать BigDecimal::longValueExact следующим образом:

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

Поскольку у вас также есть строки с десятичными цифрами, вы должны использовать форму синтаксического анализа чисел, которая может их распознавать, даже если вы не хотите сохранять эту информацию.

Этот метод выдаст ArithmeticInformation, если вы потеряете какую-либо информацию, что означает, что число не помещается в Long или имеет ненулевую дробную часть. Если вы хотите быть более снисходительным, вы можете использовать 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

Вы можете поиграть с этим небольшим фрагментом кода здесь, на Scastie.

person stefanobaghino    schedule 21.06.2018
comment
новый BigDecimal(20006916941148201619.00000000).longValue() дает неверный результат (1560172867438650003). Любой другой вариант? - person tooptoop4; 28.06.2018
comment
Это значение слишком велико для хранения в 64-битном формате, вам нужно использовать BigDecimal/BigInteger. Или вы можете создать свой собственный тип и поддержать его массивом байтов, но вы сами с этим. - person stefanobaghino; 28.06.2018