1
0
mirror of https://github.com/DanilaFe/abacus synced 2024-06-30 14:50:59 -07:00
Abacus/src/main/java/org/nwapw/abacus/number/PreciseNumber.java

155 lines
4.3 KiB
Java
Raw Normal View History

package org.nwapw.abacus.number;
import java.math.BigDecimal;
import java.math.RoundingMode;
2017-08-01 10:49:50 -07:00
/**
* A number that uses a BigDecimal to store its value,
* leading to infinite possible precision.
*/
2017-07-30 21:11:32 -07:00
public class PreciseNumber implements NumberInterface {
/**
* The number one.
*/
public static final PreciseNumber ONE = new PreciseNumber(BigDecimal.ONE);
/**
* The number zero.
*/
public static final PreciseNumber ZERO = new PreciseNumber(BigDecimal.ZERO);
/**
* The number ten.
*/
public static final PreciseNumber TEN = new PreciseNumber(BigDecimal.TEN);
/**
* The value of the PreciseNumber.
*/
BigDecimal value;
/**
* Constructs a precise number from the given string.
2017-07-30 21:11:32 -07:00
*
* @param string a string representation of the number meeting the same conditions
* as the BidDecimal(String) constructor.
*/
2017-07-30 21:11:32 -07:00
public PreciseNumber(String string) {
value = new BigDecimal(string);
}
/**
* Constructs a precise number from the given BigDecimal.
2017-07-30 21:11:32 -07:00
*
* @param value a BigDecimal object representing the value of the number.
*/
2017-07-30 21:11:32 -07:00
public PreciseNumber(BigDecimal value) {
this.value = value;
}
@Override
public int getMaxPrecision() {
2017-07-31 23:16:37 -07:00
return 65;
}
@Override
public NumberInterface multiply(NumberInterface multiplier) {
return new PreciseNumber(this.value.multiply(((PreciseNumber) multiplier).value));
}
@Override
public NumberInterface divide(NumberInterface divisor) {
return new PreciseNumber(value.divide(((PreciseNumber) divisor).value, this.getMaxPrecision(), RoundingMode.HALF_UP));
}
@Override
public NumberInterface add(NumberInterface summand) {
return new PreciseNumber(value.add(((PreciseNumber) summand).value));
}
@Override
public NumberInterface subtract(NumberInterface subtrahend) {
return new PreciseNumber(value.subtract(((PreciseNumber) subtrahend).value));
}
@Override
public NumberInterface intPow(int exponent) {
2017-07-30 21:11:32 -07:00
if (exponent == 0) {
return PreciseNumber.ONE;
}
boolean takeReciprocal = exponent < 0;
exponent = Math.abs(exponent);
NumberInterface power = this;
2017-07-30 21:11:32 -07:00
for (int currentExponent = 1; currentExponent < exponent; currentExponent++) {
power = power.multiply(this);
}
2017-07-30 21:11:32 -07:00
if (takeReciprocal) {
power = PreciseNumber.ONE.divide(power);
}
return power;
}
@Override
public int compareTo(NumberInterface number) {
return value.compareTo(((PreciseNumber) number).value);
}
@Override
public int signum() {
return value.signum();
}
@Override
public NumberInterface ceiling() {
String str = value.toPlainString();
int decimalIndex = str.indexOf('.');
if(decimalIndex != -1){
return this.floor().add(ONE);
}
return this;
}
@Override
public NumberInterface floor() {
String str = value.toPlainString();
int decimalIndex = str.indexOf('.');
if(decimalIndex != -1){
return new PreciseNumber(str.substring(0, decimalIndex));
}
return this;
}
@Override
public NumberInterface fractionalPart() {
String str = value.toPlainString();
int decimalIndex = str.indexOf('.');
if(decimalIndex != -1){
return new PreciseNumber(str.substring(decimalIndex + 1));
}
return ZERO;
}
@Override
public int intValue() {
return value.intValue();
}
@Override
2017-07-30 21:11:32 -07:00
public NumberInterface negate() {
return new PreciseNumber(value.negate());
}
@Override
public NumberInterface promoteTo(Class<? extends NumberInterface> toClass) {
2017-07-30 21:11:32 -07:00
if (toClass == this.getClass()) {
return this;
}
return null;
}
@Override
public String toString() {
2017-07-31 23:16:37 -07:00
BigDecimal rounded = value.setScale(getMaxPrecision() - 15, RoundingMode.HALF_UP);
return rounded.stripTrailingZeros().toPlainString();
}
}