Kotlin BigInteger для преобразования BigDecimal - PullRequest
0 голосов
/ 12 ноября 2018

Я пишу очень простой класс и изо всех сил пытаюсь сделать некоторое десятичное деление.

Так что это не очень хороший код, но ...

class Rational (val numerator: BigInteger, val denominator: BigInteger) : Comparable <Rational> {

     //ATTEMPT 1
     //val decimalRepresentation: BigDecimal = (numerator.toBigDecimal().div(denominator.toBigDecimal()))//.setScale(5)

     //ATTEMPT 2  
     val decimalRepresentation = (BigDecimal(numerator).div(BigDecimal(denominator))) //.setScale(5)

     override fun compareTo(other: Rational): Int {
        val a = BigDecimal(1.0)
        val b = BigDecimal(2.0)
        val x = a.divide(b) // 0.5
        println ("x: " + x.toString())

        println("this val: " + this.decimalRepresentation)
        println("other val: " + other.decimalRepresentation)

        return when {
           ...
        }
    }

Так что я 'Мы попробовали два способа преобразования BigIntegers в BigDecimals, чтобы выполнить сравнение, и оба провалились, и математика выполняет целочисленное деление

, поэтому

1/3 = 0
5/6 = 1

Я сделал poc на случай, если я сойду с ума, а х = 0,5.

Может кто-нибудь сказать мне, как это исправить (без изменения типов параметров или преобразования в строку и обратно!)

Как ни странно, 1/2 также возвращает 0, что мне кажется странным, как и ябудет ожидать от 0,5 до 1?Это заставляет меня беспокоиться, что я где-то совершенно упускаю очень простую точку!

1 Ответ

0 голосов
/ 12 ноября 2018

Одна из проблем лежит в пределах BigDecimal.div. Он использует RoundingMode.HALF_EVEN и данный scale используемого дивиденда BigDecimal (что также указано в документации). Другая проблема заключается в том, что преобразование от BigInteger до BigDecimal сначала устанавливает масштаб на 0 (проверьте также BigDecimal(BigInteger)) и, следовательно, будет округляться без использования десятичных цифр.

Обратите внимание, что в вашем примере вы использовали a.divide(b) с двумя BigDecimal первыми, а при фактическом преобразовании вы использовали a.div(b) с двумя BigInteger -трансформированными BigDecimal. Это совсем другая история; -)

Вы можете решить свою проблему одним из следующих способов:

Либо преобразуйте BigInteger, используя toBigDecimal, и укажите желаемое scale, например ::

val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)

Или вместо этого вы можете использовать divide и передать желаемый масштаб:

val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)

В этом случае я использовал 2 десятичных знака, и я округлил пополам (RoundingMode.HALF_UP) .

...