From 6d200f6948c2134f4faf4a121622aec1acbf0e3a Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Sun, 3 Jun 2018 01:54:07 +0000 Subject: [PATCH] implement floating point number formatting which matches access git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/exprs@1159 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/impl/expr/BaseNumericValue.java | 11 +++------ .../jackcess/impl/expr/BaseValue.java | 5 ++-- .../jackcess/impl/expr/BigDecimalValue.java | 6 +++-- .../jackcess/impl/expr/BuiltinOperators.java | 23 ++++++++++--------- .../jackcess/impl/expr/DefaultFunctions.java | 3 ++- .../impl/expr/DefaultNumberFunctions.java | 5 ++-- .../jackcess/impl/expr/DoubleValue.java | 9 +++++++- .../jackcess/impl/expr/LongValue.java | 7 +++++- .../impl/expr/ExpressionatorTest.java | 7 +++--- 9 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java index dd12d7c..eb1ac7e 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseNumericValue.java @@ -26,18 +26,13 @@ import com.healthmarketscience.jackcess.impl.ColumnImpl; * * @author James Ahlborn */ -public abstract class BaseNumericValue extends BaseValue +public abstract class BaseNumericValue extends BaseValue { - protected BaseNumericValue() + protected BaseNumericValue() { } - @Override - public String getAsString() { - return getNumber().toString(); - } - @Override public Integer getAsLongInt() { return roundToLongInt(); @@ -51,7 +46,7 @@ public abstract class BaseNumericValue extends BaseValue @Override public Date getAsDateTime(EvalContext ctx) { double d = getNumber().doubleValue(); - + SimpleDateFormat sdf = ctx.createDateFormat( ctx.getTemporalConfig().getDefaultDateTimeFormat()); return new Date(ColumnImpl.fromDateDouble(d, sdf.getCalendar())); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java index ef0a91b..0f081dd 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BaseValue.java @@ -22,6 +22,7 @@ import java.util.Date; import com.healthmarketscience.jackcess.expr.Value; import com.healthmarketscience.jackcess.expr.EvalContext; import com.healthmarketscience.jackcess.expr.EvalException; +import com.healthmarketscience.jackcess.impl.NumberFormatter; /** * @@ -63,10 +64,10 @@ public abstract class BaseValue implements Value } protected Integer roundToLongInt() { - return getAsBigDecimal().setScale(0, BuiltinOperators.ROUND_MODE) + return getAsBigDecimal().setScale(0, NumberFormatter.ROUND_MODE) .intValueExact(); } - + @Override public String toString() { return "Value[" + getType() + "] '" + get() + "'"; diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BigDecimalValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BigDecimalValue.java index 3b64c51..89e4004 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BigDecimalValue.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BigDecimalValue.java @@ -18,6 +18,8 @@ package com.healthmarketscience.jackcess.impl.expr; import java.math.BigDecimal; +import com.healthmarketscience.jackcess.impl.NumberFormatter; + /** * * @author James Ahlborn @@ -26,7 +28,7 @@ public class BigDecimalValue extends BaseNumericValue { private final BigDecimal _val; - public BigDecimalValue(BigDecimal val) + public BigDecimalValue(BigDecimal val) { _val = val; } @@ -51,7 +53,7 @@ public class BigDecimalValue extends BaseNumericValue @Override public String getAsString() { - return _val.toPlainString(); + return NumberFormatter.format(_val); } @Override diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java index 6d768a1..e0f6e25 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java @@ -17,8 +17,6 @@ limitations under the License. package com.healthmarketscience.jackcess.impl.expr; import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; import java.text.DateFormat; import java.util.Date; import java.util.regex.Pattern; @@ -27,6 +25,7 @@ import com.healthmarketscience.jackcess.expr.EvalContext; import com.healthmarketscience.jackcess.expr.EvalException; import com.healthmarketscience.jackcess.expr.Value; import com.healthmarketscience.jackcess.impl.ColumnImpl; +import com.healthmarketscience.jackcess.impl.NumberFormatter; /** @@ -58,9 +57,6 @@ public class BuiltinOperators public static final Value EMPTY_STR_VAL = new StringValue(""); public static final Value ZERO_VAL = FALSE_VAL; - public static final RoundingMode ROUND_MODE = RoundingMode.HALF_EVEN; - public static final MathContext MATH_CONTEXT = - new MathContext(28, ROUND_MODE); private enum CoercionType { SIMPLE(true, true), GENERAL(false, true), COMPARE(false, false); @@ -109,7 +105,8 @@ public class BuiltinOperators return toValue(-param1.getAsDouble()); case STRING: case BIG_DEC: - return toValue(param1.getAsBigDecimal().negate(MATH_CONTEXT)); + return toValue(param1.getAsBigDecimal().negate( + NumberFormatter.DEC_MATH_CONTEXT)); default: throw new EvalException("Unexpected type " + mathType); } @@ -140,7 +137,8 @@ public class BuiltinOperators return toValue(param1.getAsDouble() + param2.getAsDouble()); case BIG_DEC: return toValue(param1.getAsBigDecimal().add( - param2.getAsBigDecimal(), MATH_CONTEXT)); + param2.getAsBigDecimal(), + NumberFormatter.DEC_MATH_CONTEXT)); default: throw new EvalException("Unexpected type " + mathType); } @@ -169,7 +167,8 @@ public class BuiltinOperators return toValue(param1.getAsDouble() - param2.getAsDouble()); case BIG_DEC: return toValue(param1.getAsBigDecimal().subtract( - param2.getAsBigDecimal(), MATH_CONTEXT)); + param2.getAsBigDecimal(), + NumberFormatter.DEC_MATH_CONTEXT)); default: throw new EvalException("Unexpected type " + mathType); } @@ -195,7 +194,8 @@ public class BuiltinOperators return toValue(param1.getAsDouble() * param2.getAsDouble()); case BIG_DEC: return toValue(param1.getAsBigDecimal().multiply( - param2.getAsBigDecimal(), MATH_CONTEXT)); + param2.getAsBigDecimal(), + NumberFormatter.DEC_MATH_CONTEXT)); default: throw new EvalException("Unexpected type " + mathType); } @@ -263,7 +263,8 @@ public class BuiltinOperators // (must be a positive int exponent) try { BigDecimal result = param1.getAsBigDecimal().pow( - param2.getAsBigDecimal().intValueExact(), MATH_CONTEXT); + param2.getAsBigDecimal().intValueExact(), + NumberFormatter.DEC_MATH_CONTEXT); return toValue(result); } catch(ArithmeticException ae) { // fall back to general handling via doubles... @@ -764,7 +765,7 @@ public class BuiltinOperators } static BigDecimal divide(BigDecimal num, BigDecimal denom) { - return num.divide(denom, MATH_CONTEXT); + return num.divide(denom, NumberFormatter.DEC_MATH_CONTEXT); } static boolean isIntegral(double d) { diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java index a10b557..7acca2c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java @@ -27,6 +27,7 @@ import com.healthmarketscience.jackcess.expr.Function; import com.healthmarketscience.jackcess.expr.FunctionLookup; import com.healthmarketscience.jackcess.expr.Value; import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.impl.NumberFormatter; /** * @@ -365,7 +366,7 @@ public class DefaultFunctions @Override protected Value eval1(EvalContext ctx, Value param1) { BigDecimal bd = param1.getAsBigDecimal(); - bd = bd.setScale(4, BuiltinOperators.ROUND_MODE); + bd = bd.setScale(4, NumberFormatter.ROUND_MODE); return BuiltinOperators.toValue(bd); } }); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java index 33ab133..4389d9f 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java @@ -22,6 +22,7 @@ import com.healthmarketscience.jackcess.expr.EvalContext; import com.healthmarketscience.jackcess.expr.EvalException; import com.healthmarketscience.jackcess.expr.Function; import com.healthmarketscience.jackcess.expr.Value; +import com.healthmarketscience.jackcess.impl.NumberFormatter; import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*; /** @@ -56,7 +57,7 @@ public class DefaultNumberFunctions case STRING: case BIG_DEC: return BuiltinOperators.toValue(param1.getAsBigDecimal().abs( - BuiltinOperators.MATH_CONTEXT)); + NumberFormatter.DEC_MATH_CONTEXT)); default: throw new EvalException("Unexpected type " + mathType); } @@ -138,7 +139,7 @@ public class DefaultNumberFunctions scale = params[1].getAsLongInt(); } BigDecimal bd = param1.getAsBigDecimal() - .setScale(scale, BuiltinOperators.ROUND_MODE); + .setScale(scale, NumberFormatter.ROUND_MODE); return BuiltinOperators.toValue(bd); } }); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DoubleValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DoubleValue.java index 7fcd840..7f68ad8 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DoubleValue.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DoubleValue.java @@ -18,6 +18,8 @@ package com.healthmarketscience.jackcess.impl.expr; import java.math.BigDecimal; +import com.healthmarketscience.jackcess.impl.NumberFormatter; + /** * * @author James Ahlborn @@ -26,7 +28,7 @@ public class DoubleValue extends BaseNumericValue { private final Double _val; - public DoubleValue(Double val) + public DoubleValue(Double val) { _val = val; } @@ -58,4 +60,9 @@ public class DoubleValue extends BaseNumericValue public BigDecimal getAsBigDecimal() { return BigDecimal.valueOf(_val); } + + @Override + public String getAsString() { + return NumberFormatter.format(_val); + } } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java index 217a5ee..3a47a84 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/LongValue.java @@ -26,7 +26,7 @@ public class LongValue extends BaseNumericValue { private final Integer _val; - public LongValue(Integer val) + public LongValue(Integer val) { _val = val; } @@ -58,4 +58,9 @@ public class LongValue extends BaseNumericValue public BigDecimal getAsBigDecimal() { return BigDecimal.valueOf(_val); } + + @Override + public String getAsString() { + return _val.toString(); + } } diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java index 49db5bd..2f6e738 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java @@ -30,6 +30,7 @@ import com.healthmarketscience.jackcess.expr.Function; import com.healthmarketscience.jackcess.expr.Identifier; import com.healthmarketscience.jackcess.expr.TemporalConfig; import com.healthmarketscience.jackcess.expr.Value; +import com.healthmarketscience.jackcess.impl.NumberFormatter; import junit.framework.TestCase; /** @@ -326,7 +327,7 @@ public class ExpressionatorTest extends TestCase public void testLiteralDefaultValue() throws Exception { - assertEquals("-28.0 blah ", eval("=CDbl(9)-37 & \" blah \"", + assertEquals("-28 blah ", eval("=CDbl(9)-37 & \" blah \"", Value.Type.STRING)); assertEquals("CDbl(9)-37 & \" blah \"", eval("CDbl(9)-37 & \" blah \"", Value.Type.STRING)); @@ -385,12 +386,12 @@ public class ExpressionatorTest extends TestCase } static int roundToLongInt(double d) { - return new BigDecimal(d).setScale(0, BuiltinOperators.ROUND_MODE) + return new BigDecimal(d).setScale(0, NumberFormatter.ROUND_MODE) .intValueExact(); } static BigDecimal toBD(double d) { - return toBD(new BigDecimal("" + d)); + return toBD(BigDecimal.valueOf(d)); } static BigDecimal toBD(BigDecimal bd) { -- 2.39.5