Expressions with BigDecimal Java / Kotlin

Viewed 4502

I need help from those who understand Java / Kotlin.

I would like to perform some calculations with BigDecimal

How would the expression below look using BigDecimal?

(1 + 0.02) ^ (1 / 251) - 1

I tried to do like this:

val x = (BigDecimal.ONE + BigDecimal(0.02)).pow(1/251) - 1

However, dividing 1 by 251 is not accurate and this expression always returns 0

2 Answers

Numeric literals

Do not use numeric literals when constructing a BigDecimal.

If you write new BigDecimal( 0.02 ), such a literal is first processed by the compiler as a float or double primitive. The resulting float or double is then passed to the BigDecimal constructor being called via new.

The float & double types are based on floating-point technology. Floating-point trades away accuracy for performance (fast execution).

So your use of a literal introduces inaccuracy, defeating the first of the two purposes for using BigDecimal: (a) accuracy, and (b) handling very large/small numbers.

So construct a BigDecimal by passing text rather than numbers. Example in Java syntax:

new BigDecimal( "0.02" )

Use method calls, not use Java math operators

You cannot the operators +-*/ with BigDecimal objects, at least not in Java (I do not know Kotlin).

To add BigDecimal objects, call plus method. To subtract, call subtract. And so on. Example in Java syntax:

BigDecimal sum = BigDecimal.ONE.plus( new BigDecimal( "0.02" ) ) ;

Constructors

Use new to construct each BigDecimal object. Your code + BigDecimal(…should have been + new BigDecimal(…. Well, at least in Java… again, I do not know Kotlin.

Sample

Your code, apparently in Kotlin.

val x = (BigDecimal.ONE + BigDecimal(0.02)).pow(1/251) - 1

…should be more like this, at least in Java (versus Kotlin):

BigDecimal sum = BigDecimal.ONE.plus( new BigDecimal( "0.02" ) ) ;
BigDecimal exponent = BigDecimal.ONE.divide( new BigDecimal( "251" ) ;
BigDecimal pow = sum.pow( exponent ) ) ;
BigDecimal subtraction = pow.subtract( BigDecimal.ONE ) ;

Notice that I recommend breaking up the parts of the math work, using multiple lines of code. I do so to make the code easier to read, and easier to test, trace, and verify.

Caveat: That code is off-the-cuff, untested. And, I am no math wiz.

Caveat: I ignored issues of rounding. You may want to call the variants of the methods that take a MathContext to perform rounding, depending on the context of your work.

dividing 1 by 251 is not accurate and this expression always returns 0

This would result in Integer division, To cure integer division you can do 1.00/251.

Also you are missing a new before BigDecimal(0.02), but even if you did there there is no operator + for BigDecimal and the plus method should be used.

Related