Kotlin BigInteger to BigDecimal conversion
I'm writing a very simple class and I'm struggling to do some decimal division.
So this is not great code but ...
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 {
...
}
}
So I've tried two ways of converting the BigIntegers into BigDecimals to do the compare and both fail and the maths performs integer division
so
1 / 3 = 0
5 / 6 = 1
I've done a poc in case I'm going mad and x is 0.5.
Could anyone tell me how to fix this (without changing parameter types or converting to a string and back!)
Oddly 1 / 2 is returning 0 as well which seems odd to me as I would expect 0.5 to round to 1 ? This makes me worry that I'm completely missing a very simple point somewhere!
java kotlin biginteger bigdecimal
add a comment |
I'm writing a very simple class and I'm struggling to do some decimal division.
So this is not great code but ...
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 {
...
}
}
So I've tried two ways of converting the BigIntegers into BigDecimals to do the compare and both fail and the maths performs integer division
so
1 / 3 = 0
5 / 6 = 1
I've done a poc in case I'm going mad and x is 0.5.
Could anyone tell me how to fix this (without changing parameter types or converting to a string and back!)
Oddly 1 / 2 is returning 0 as well which seems odd to me as I would expect 0.5 to round to 1 ? This makes me worry that I'm completely missing a very simple point somewhere!
java kotlin biginteger bigdecimal
1
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57
add a comment |
I'm writing a very simple class and I'm struggling to do some decimal division.
So this is not great code but ...
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 {
...
}
}
So I've tried two ways of converting the BigIntegers into BigDecimals to do the compare and both fail and the maths performs integer division
so
1 / 3 = 0
5 / 6 = 1
I've done a poc in case I'm going mad and x is 0.5.
Could anyone tell me how to fix this (without changing parameter types or converting to a string and back!)
Oddly 1 / 2 is returning 0 as well which seems odd to me as I would expect 0.5 to round to 1 ? This makes me worry that I'm completely missing a very simple point somewhere!
java kotlin biginteger bigdecimal
I'm writing a very simple class and I'm struggling to do some decimal division.
So this is not great code but ...
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 {
...
}
}
So I've tried two ways of converting the BigIntegers into BigDecimals to do the compare and both fail and the maths performs integer division
so
1 / 3 = 0
5 / 6 = 1
I've done a poc in case I'm going mad and x is 0.5.
Could anyone tell me how to fix this (without changing parameter types or converting to a string and back!)
Oddly 1 / 2 is returning 0 as well which seems odd to me as I would expect 0.5 to round to 1 ? This makes me worry that I'm completely missing a very simple point somewhere!
java kotlin biginteger bigdecimal
java kotlin biginteger bigdecimal
edited Nov 12 '18 at 14:26
Roland
9,41711141
9,41711141
asked Nov 12 '18 at 12:55
gringogordo
52011031
52011031
1
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57
add a comment |
1
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57
1
1
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57
add a comment |
1 Answer
1
active
oldest
votes
One of the problems lies within BigDecimal.div. It uses the RoundingMode.HALF_EVEN and the given scale of the used dividend BigDecimal (which is also stated in the documentation). The other problem is that the BigInteger to BigDecimal-transformation first sets the scale to 0 (check also BigDecimal(BigInteger)) and therefore it will round without using decimal digits.
Note also that on your sample you used a.divide(b) with two BigDecimal first and on the actual transformation you used a.div(b) with two BigInteger-transformed BigDecimal. That's a completely different story ;-)
You can solve your issue with one of the following:
Either transform your BigInteger using toBigDecimal and specify a desired scale, e.g.:
val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)
Or you may want to use divide instead and pass the desired scale:
val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)
In this case I used 2 decimal digits and I am rounding up on half (RoundingMode.HALF_UP).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262639%2fkotlin-biginteger-to-bigdecimal-conversion%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
One of the problems lies within BigDecimal.div. It uses the RoundingMode.HALF_EVEN and the given scale of the used dividend BigDecimal (which is also stated in the documentation). The other problem is that the BigInteger to BigDecimal-transformation first sets the scale to 0 (check also BigDecimal(BigInteger)) and therefore it will round without using decimal digits.
Note also that on your sample you used a.divide(b) with two BigDecimal first and on the actual transformation you used a.div(b) with two BigInteger-transformed BigDecimal. That's a completely different story ;-)
You can solve your issue with one of the following:
Either transform your BigInteger using toBigDecimal and specify a desired scale, e.g.:
val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)
Or you may want to use divide instead and pass the desired scale:
val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)
In this case I used 2 decimal digits and I am rounding up on half (RoundingMode.HALF_UP).
add a comment |
One of the problems lies within BigDecimal.div. It uses the RoundingMode.HALF_EVEN and the given scale of the used dividend BigDecimal (which is also stated in the documentation). The other problem is that the BigInteger to BigDecimal-transformation first sets the scale to 0 (check also BigDecimal(BigInteger)) and therefore it will round without using decimal digits.
Note also that on your sample you used a.divide(b) with two BigDecimal first and on the actual transformation you used a.div(b) with two BigInteger-transformed BigDecimal. That's a completely different story ;-)
You can solve your issue with one of the following:
Either transform your BigInteger using toBigDecimal and specify a desired scale, e.g.:
val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)
Or you may want to use divide instead and pass the desired scale:
val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)
In this case I used 2 decimal digits and I am rounding up on half (RoundingMode.HALF_UP).
add a comment |
One of the problems lies within BigDecimal.div. It uses the RoundingMode.HALF_EVEN and the given scale of the used dividend BigDecimal (which is also stated in the documentation). The other problem is that the BigInteger to BigDecimal-transformation first sets the scale to 0 (check also BigDecimal(BigInteger)) and therefore it will round without using decimal digits.
Note also that on your sample you used a.divide(b) with two BigDecimal first and on the actual transformation you used a.div(b) with two BigInteger-transformed BigDecimal. That's a completely different story ;-)
You can solve your issue with one of the following:
Either transform your BigInteger using toBigDecimal and specify a desired scale, e.g.:
val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)
Or you may want to use divide instead and pass the desired scale:
val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)
In this case I used 2 decimal digits and I am rounding up on half (RoundingMode.HALF_UP).
One of the problems lies within BigDecimal.div. It uses the RoundingMode.HALF_EVEN and the given scale of the used dividend BigDecimal (which is also stated in the documentation). The other problem is that the BigInteger to BigDecimal-transformation first sets the scale to 0 (check also BigDecimal(BigInteger)) and therefore it will round without using decimal digits.
Note also that on your sample you used a.divide(b) with two BigDecimal first and on the actual transformation you used a.div(b) with two BigInteger-transformed BigDecimal. That's a completely different story ;-)
You can solve your issue with one of the following:
Either transform your BigInteger using toBigDecimal and specify a desired scale, e.g.:
val scale = 10 // decimal digits
val decimalRepresentation = numerator.toBigDecimal(scale) / denominator.toBigDecimal(scale)
Or you may want to use divide instead and pass the desired scale:
val decimalRepresentation = BigDecimal(numerator).divide(BigDecimal(denominator), 2, RoundingMode.HALF_UP)
In this case I used 2 decimal digits and I am rounding up on half (RoundingMode.HALF_UP).
edited Nov 12 '18 at 15:53
Rudy Velthuis
24.1k43474
24.1k43474
answered Nov 12 '18 at 13:19
Roland
9,41711141
9,41711141
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262639%2fkotlin-biginteger-to-bigdecimal-conversion%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You shouldn't convert to BigDecimal for the purpose of comparing. Consider comparing (1/3) with (2000000001/600000000). You have to choose a certain arbitrary scale - say, 5 - when converting to BigDecimal. Both the above numbers would give you 0.33333, yet they're obviously not equal. You should, instead, compare the numerators and denominators directly. Find the lowest common multiple of the two denominators and convert the fractions and compare numerators.
– DodgyCodeException
Nov 12 '18 at 14:48
Yes good point thanks
– gringogordo
Nov 12 '18 at 14:57