-- Short Solution --
Thank you for all the informative replies... @PetrJaneček @Matt pointed me in the right direction. I agree I had to brush up on my understanding of floating point arithmetic; but the difference in calling the constructor vs double's canonical string representation by using valueOf solved my problem.
private static Double sampleRound(Double value, int places) {
BigDecimal bd1 = BigDecimal.valueOf(value);
bd1 = bd1.setScale(places, RoundingMode.HALF_UP);
return bd1.doubleValue();
}
As provided by @PetrJaneček a useful video:
-- Original Question --
I've come across a really odd one regarding rounding and just want to understand where I'm going wrong.
The function is:
private static Double sampleRound(Double value, int places) {
BigDecimal bd1 = new BigDecimal(value);
bd1 = bd1.setScale(places, RoundingMode.HALF_UP);
return bd1.doubleValue();
}
If I pass the value "1942.945", I would expect it to output "1942.95", but instead I get "1942.94". However if I pass "1942.9451" I get "1942.95". So ok fair then let's assume I carry over this logic to 3 decimal places instead. So if I pass "1942.9445" I expect "1942.944", but instead I get "1942.945", how and why? The logic seems broken to me?
sampleRound(1942.945, 2) -> 1942.94
[Does NOT make sense, should be 1942.95]
sampleRound(1942.9450000000001, 2)-> 1942.95
*Edit: I've also passed this (1 additional zero), again I understand data types and it's constraints, I guess the point I'm making is the fraction .005 isn't being seen as a half up >= 5: in accordance with the documentation of java "discarded fraction is ≥ 0.5;" it's essentially seeing it as > 0.5 not >= 0.5 *
sampleRound(1942.94500000000001, 2) -> 1942.94
[Then this should be equivalent to the top]
Ok but then fine I can deal with the above logic, but as soon as I do 3 decimal places:
sampleRound(1942.9445, 3) -> 1942.945
[Does NOT make sense, in accordance with top logic should be 19423.944]. Then just like I mentioned in the above logic where franaction .005 isn't being seen as a >= 0.5 then .0005 should be treated the same way?
I hope by description makes sense, but I'm stumped?
Regards,