introduce ToBigDecimal functions

This commit is contained in:
Jonathan Shook 2020-04-17 13:54:19 -05:00
parent 5811dbf469
commit dcff4dbd64
7 changed files with 280 additions and 0 deletions

View File

@ -0,0 +1,46 @@
package io.nosqlbench.virtdata.library.basics.shared.from_double.to_bigdecimal;
import io.nosqlbench.nb.api.errors.BasicError;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.library.basics.shared.util.MathContextReader;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.function.DoubleFunction;
import java.util.function.LongFunction;
@ThreadSafeMapper
public class ToBigDecimal implements DoubleFunction<BigDecimal> {
private final MathContext mathContext;
@Example({"ToBigDecimal()", "Convert all double values to BigDecimal values with no limits (using MathContext" +
".UNLIMITED)"})
public ToBigDecimal() {
this.mathContext = MathContext.UNLIMITED;
}
/**
* Convert all input values to BigDecimal values with a specific MathContext.
* The value for context can be one of UNLIMITED,
* DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by
* {@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}.
* In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like
* UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.
*/
@Example({"ToBigDecimal('DECIMAL32')", "IEEE 754R Decimal32 format, 7 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL64'),", "IEEE 754R Decimal64 format, 16 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL128')", "IEEE 754R Decimal128 format, 34 digits, HALF_EVEN"})
@Example({"ToBigDecimal('UNLIMITED')", "unlimited precision, HALF_UP"})
@Example({"ToBigDecimal('precision=17 roundingMode=UNNECESSARY')", "Custom precision with no rounding performed"})
public ToBigDecimal(String context) {
this.mathContext = MathContextReader.getMathContext(context);
}
@Override
public BigDecimal apply(double value) {
return new BigDecimal(value, mathContext);
}
}

View File

@ -0,0 +1,45 @@
package io.nosqlbench.virtdata.library.basics.shared.from_int.to_bigdecimal;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.library.basics.shared.util.MathContextReader;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.function.DoubleFunction;
import java.util.function.IntFunction;
@ThreadSafeMapper
public class ToBigDecimal implements IntFunction<BigDecimal> {
private final MathContext mathContext;
@Example({"ToBigDecimal()", "Convert all int values to BigDecimal values with no limits (using MathContext" +
".UNLIMITED)"})
public ToBigDecimal() {
this.mathContext = MathContext.UNLIMITED;
}
/**
* Convert all input values to BigDecimal values with a specific MathContext.
* The value for context can be one of UNLIMITED,
* DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by
* {@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}.
* In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like
* UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.
*/
@Example({"ToBigDecimal('DECIMAL32')", "IEEE 754R Decimal32 format, 7 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL64'),", "IEEE 754R Decimal64 format, 16 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL128')", "IEEE 754R Decimal128 format, 34 digits, HALF_EVEN"})
@Example({"ToBigDecimal('UNLIMITED')", "unlimited precision, HALF_UP"})
@Example({"ToBigDecimal('precision=17 roundingMode=UNNECESSARY')", "Custom precision with no rounding performed"})
public ToBigDecimal(String context) {
this.mathContext = MathContextReader.getMathContext(context);
}
@Override
public BigDecimal apply(int value) {
return new BigDecimal(value, mathContext);
}
}

View File

@ -0,0 +1,59 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_bigdecimal;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import io.nosqlbench.virtdata.library.basics.shared.util.MathContextReader;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.function.LongFunction;
/**
* Convert values to BigDecimals at configurable scale or precision.
*/
@ThreadSafeMapper
public class ToBigDecimal implements LongFunction<BigDecimal> {
private final MathContext mathContext;
private final int scale;
@Example({"ToBigDecimal()", "Convert all long values to whole-numbered BigDecimal values"})
public ToBigDecimal() {
this(0);
}
@Example({"ToBigDecimal(0)", "Convert all long values to whole-numbered BigDecimal values"})
@Example({"ToBigDecimal(2)", "Convert long 'pennies' BigDecimal with 2 digits after decimal point"})
public ToBigDecimal(int scale) {
this.scale = scale;
this.mathContext=null;
}
/**
* Convert all input values to BigDecimal values with a specific MathContext. This form is only
* supported for scale=0, meaning whole numbers. The value for context can be one of UNLIMITED,
* DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by
* {@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}.
* In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like
* UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.
*/
@Example({"ToBigDecimal('DECIMAL32')","IEEE 754R Decimal32 format, 7 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL64'),","IEEE 754R Decimal64 format, 16 digits, HALF_EVEN"})
@Example({"ToBigDecimal('DECIMAL128')","IEEE 754R Decimal128 format, 34 digits, HALF_EVEN"})
@Example({"ToBigDecimal('UNLIMITED')","unlimited precision, HALF_UP"})
@Example({"ToBigDecimal('precision=17 roundingMode=UNNECESSARY')","Custom precision with no rounding performed"})
public ToBigDecimal(String context) {
this.scale=Integer.MIN_VALUE;
this.mathContext = MathContextReader.getMathContext(context);
}
@Override
public BigDecimal apply(long value) {
if (mathContext!=null) {
return new BigDecimal(value,mathContext);
} else {
return BigDecimal.valueOf(value,scale);
}
}
}

View File

@ -0,0 +1,38 @@
package io.nosqlbench.virtdata.library.basics.shared.from_string.to_bigdecimal;
import io.nosqlbench.virtdata.api.annotations.Example;
import io.nosqlbench.virtdata.library.basics.shared.util.MathContextReader;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.function.Function;
public class ToBigDecimal implements Function<String, BigDecimal> {
private final MathContext context;
@Example({"Convert strings to BigDecimal according to default precision (unlimited) and rounding (HALF_UP)"})
public ToBigDecimal() {
this.context = MathContext.UNLIMITED;
}
/**
* Convert all input values to BigDecimal values with a specific MathContext. This form is only
* supported for scale=0, meaning whole numbers. The value for context can be one of UNLIMITED,
* DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by
* {@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}.
* In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like
* UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.
*/
public ToBigDecimal(String context) {
this.context =
MathContextReader.getMathContext(context);
}
@Override
public BigDecimal apply(String s) {
return new BigDecimal(s, context);
}
}

View File

@ -0,0 +1,31 @@
package io.nosqlbench.virtdata.library.basics.shared.util;
import io.nosqlbench.nb.api.errors.BasicError;
import java.math.MathContext;
public class MathContextReader {
public static MathContext getMathContext(String name) {
try {
switch (name.toLowerCase()) {
case "unlimited":
return MathContext.UNLIMITED;
case "decimal32":
return MathContext.DECIMAL32;
case "decimal64":
return MathContext.DECIMAL64;
case "decimal128":
return MathContext.DECIMAL128;
default:
return new MathContext(name);
}
} catch (IllegalArgumentException iae) {
throw new BasicError("'" + name + "' was not a valid format for a new MathContext(String), try something " +
"like 'precision=17 roundingMode=UP");
}
}
}

View File

@ -0,0 +1,30 @@
package io.nosqlbench.virtdata.library.basics.shared.from_double.to_bigdecimal;
import org.assertj.core.data.Offset;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.MathContext;
import static org.assertj.core.api.Assertions.assertThat;
public class ToBigDecimalTest {
@Test
public void demonstrateDoubleToBigDecimal() {
double big = 1234567890.098765d;
System.out.println(big);
ToBigDecimal unlimited = new ToBigDecimal();
BigDecimal bignum = unlimited.apply(big);
assertThat(bignum.doubleValue()).isCloseTo(big, Offset.offset(0.000001d));
assertThat(bignum).isEqualTo(new BigDecimal(big, MathContext.UNLIMITED));
ToBigDecimal p5rounded = new ToBigDecimal("precision=5 roundingMode=UP");
BigDecimal rounded = p5rounded.apply(big);
assertThat(rounded.doubleValue()).isCloseTo(1234600000.0D,Offset.offset(0.0000001d));
System.out.println(rounded);
}
}

View File

@ -0,0 +1,31 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_bigdecimal;
import org.assertj.core.data.Offset;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.MathContext;
import static org.assertj.core.api.Assertions.assertThat;
public class ToBigDecimalTest {
@Test
public void demonstrateLongToBigDecimal() {
ToBigDecimal wholeValues = new ToBigDecimal();
BigDecimal whole12345 = wholeValues.apply(12345L);
assertThat(whole12345).isEqualTo(new BigDecimal(12345L));
ToBigDecimal pennies = new ToBigDecimal(2);
BigDecimal pennies12345 = pennies.apply(12345L);
assertThat(pennies12345).isEqualTo(BigDecimal.valueOf(12345,2));
ToBigDecimal custom = new ToBigDecimal("precision=5 roundingMode=CEILING");
BigDecimal c123456 = custom.apply(123456L);
assertThat(c123456).isEqualTo(new BigDecimal(123456L,new MathContext("precision=5 roundingMode=CEILING")));
double v = c123456.doubleValue();
assertThat(v).isCloseTo(123460d, Offset.offset(0.001d));
}
}