GordonM
GordonM

Reputation: 31730

Any number type to BigDecimal

After a lot of messing around I came up with the following code to convert any Number subclass into a BigDecimal.

I'm not convinced however that this code is fully correct. I'm certainly not happy about how verbose it is!

Is there a better way of doing this, and are there any pitfalls to this approach of which I need to be aware (other than floating point imprecise representation issues of which I'm already aware)?

public DecimalSpec setValue (Number value) {
    if (value instanceof Double) {
        if ((((Double) value).isNaN ())
        || (((Double) value).isInfinite ())) {
            throw new IllegalArgumentException ("Infinite or NaN values not allowed");
        }
    }
    this.value  = new BigDecimal (value.toString ());
    return this;
}

Upvotes: 0

Views: 2851

Answers (2)

afsantos
afsantos

Reputation: 5208

I'm not aware of any way to write it in less code, as in some method that would shortcut part of the code. However, I'd probably overload the method for Double, or let BigDecimal throw a NumberFormatException instead.

Letting BigDecimal do the work:

/** May throw NumberFormatException or NullPointerException. */
public DecimalSpec setValue (Number value) {
    this.value  = new BigDecimal (value.toString ());
    return this;
}

Overloading for Double:

/** May throw NullPointerException. */
public DecimalSpec setValue (Number value) {
    this.value  = new BigDecimal (value.toString ());
    return this;
}

/** May throw NullPointerException or IllegalArgumentException. */
public DecimalSpec setValue (Double value) {
    if (value.isNaN () || value.isInfinite ()) {
        throw new IllegalArgumentException ("Infinite or NaN values not allowed");
    }
    return this.setValue ((Number) value);
}

Upvotes: 2

jpmc26
jpmc26

Reputation: 29856

I think you have a design problem. Make setValue take a BigDecimal to begin with. Then the code that converts other types to BigDecimal can be elsewhere in your code. You'll have the freedom to overload the BigDecimal conversion for various types, and you can do a conversion to BigDecimal based specifically on the input type.

E.g.,

public class BigDecimalConverter {
    public static toBigDecimal(int i) { ... }
    public static toBigDecimal(double i) { ... }
    ...
}

Then

public DecimalSpec setValue (BigDecimal value) {
    this.value  = value;
    return this;
}

and

decimalSpec.setValue(BigDecimalConverter.toBigDecimal(myNumber));

Not perfect, of course, but that's the general idea. One piece of code should never do too much work. If it's necessary to accept an unknown type for conversion at some point, you might consider a converter interface and then a factory class (might not be the right pattern name) to give you the right one.

Upvotes: 1

Related Questions