In Java9, the BigDecimal # ROUND_ ~ system has finally become @ Deprecated.
Nevertheless, in blogs and entries that explain BigDecimal, when explaining BigDecimal # setScale, BigDecimal # divide, etc., it is explained usingBigDecimal # ROUND_ ~system. What do you mean? It's all @Deprecated in Java 9, right?
I decided to write an article because I feel uncomfortable recently.
First of all, from the basics.
It is basically generated by the following method.
BigDecimal value = BigDecimal.valueOf(1234.567);//Generation from a numerical system
BigDecimal value = new BigDecimal("1234.567");//Generated from a string
Since 0, 1, and 10 are already defined, use them.
BigDecimal.ZERO
BigDecimal.ONE
BigDecimal.TEN
Generation from a string is as specified by the string for scale.
System.out.println(new BigDecimal("1234.567").scale()); // → 3
System.out.println(new BigDecimal("1234.56700").scale());// → 5
Use BigDecimal # valueOf to generate from a number (double). It would be ridiculous to generate it with new.
BigDecimal value = new BigDecimal(1234.567);// NG!!Generation from a numerical system
System.out.println(value);// → 1234.5670000000000072759576141834259033203125
ResultSet#getBigDecimal
When getting from ResultSet, there is ResultSet # getBigDecimal, so use this.
BigDecimal value = rs.getBigDecimal("COL");
The following is useless, so NG
BigDecimal value = BigDecimal.valueOf(rs.getDouble("COL"));
BigDecimal value = new BigDecimal(rs.getString("COL"));
BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);
// value = a + b
BigDecimal value = a.add(b);
System.out.println(value);// 579
BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);
// value = a - b
BigDecimal value = a.subtract(b);
System.out.println(value);// -333
BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);
// value = a * b
BigDecimal value = a.multiply(b);
System.out.println(value);// 56088
Use BigDecimal # scaleByPowerOfTen.
BigDecimal src = BigDecimal.valueOf(0.123);
BigDecimal value = src.scaleByPowerOfTen(2);//Hundredfold(10 squared)
System.out.println(value);// 12.3
It's a lot cleaner than src.multiply (BigDecimal.valueOf (100)), and you don't have to create an instance of 100.
Use BigDecimal # negate.
BigDecimal src = BigDecimal.valueOf(123);
BigDecimal value = src.negate();
System.out.println(value);// -123
Please stop writing the following.
BigDecimal value = src.multiply(BigDecimal.valueOf(-1));
import java.math.RoundingMode;
//・ ・ ・
BigDecimal a = BigDecimal.valueOf(123);
BigDecimal b = BigDecimal.valueOf(456);
// value = a / b
BigDecimal value = a.divide(b, 3 /* ← scale */, RoundingMode.HALF_UP /*← Rounding*/);
System.out.println(value);// 0.270
RoundingMode are not availableThe following writing style is NG
BigDecimal value = a.divide(b, 3, BigDecimal.ROUND_HALF_UP);
For more information on Rounding Mode, please see [at the bottom](#rounding mode) for details.
scaleThere is also a BigDecimal # divide method that does not specify a scale,
When it is not divisible, ʻArithmeticException will occur, so it is better to use the scale` specified version.
Use BigDecimal # scaleByPowerOfTen.
BigDecimal src = BigDecimal.valueOf(8);
BigDecimal value = src.scaleByPowerOfTen(-2);// 1/100(10-Squared)
System.out.println(value);// 0.08
import java.math.RoundingMode;
//・ ・ ・
BigDecimal src = BigDecimal.valueOf(123.456);
//Rounding
BigDecimal value = src.setScale(2, RoundingMode.HALF_UP);
System.out.println(value); // → 123.46
//Round up
BigDecimal value = src.setScale(2, RoundingMode.UP);
//Truncate
BigDecimal value = src.setScale(2, RoundingMode.DOWN);
RoundingMode are not availableThe following writing style is NG
BigDecimal value = src.setScale(2, BigDecimal.ROUND_HALF_UP);
For more information on Rounding Mode, please see [at the bottom](#rounding mode) for details.
BigDecimal#toPlainString
BigDecimal # toString can be exponential notation, so I think it's better to use BigDecimal # toPlainString.
BigDecimal value = new BigDecimal("0.0000001");
System.out.println(value.toString()); // → 1E-7
System.out.println(value.toPlainString());// → 0.0000001
jackson also has an option to use toPlainString.
JsonGenerator.Feature.html#WRITE_BIGDECIMAL_AS_PLAIN
0 at the end of the decimalBoth BigDecimal # toString and BigDecimal # toPlainString take scale into the string and are retained even if the decimal number is followed by 0.
If you want to turn this off, use BigDecimal # stripTrailingZeros.
You don't have to work hard with regular expressions.
BigDecimal value = new BigDecimal("1.000000");
System.out.println(value); // → 1.000000
System.out.println(value.stripTrailingZeros());// → 1
BigDecimal # stripTrailingZeros has a bug up to java7.
JDK-6480539 : BigDecimal.stripTrailingZeros() has no effect on zero itself ("0.0")・long ・ double`BigDecimal value = BigDecimal.valueOf(12345);
int i = value.intValue();
long l = value.longValue();
double d = value.doubleValue();
There are also float and BigInteger.
There is a version of the conversion to integers that throws an exception when there is information that is lost out of tolerance. Conversely, the normal version is ignored even if information is lost.
int i = value.intValueExact();
long l = value.longValueExact();
There are also byte, short and BigInteger versions of the -ValueExact family of methods.
Since BigDecimal # equals returns false if scale does not match,
If you are writing a system that you are not interested in, such as scale, you should judge whether the result of compareTo matches 0.
BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2
System.out.println(value1.equals(value2)); // false
System.out.println(value1.compareTo(value2) == 0);// true
HashMapBigDecimal # equals ・ BigDecimal # hashCode also considers scale, so
Writing a system that you are not interested in, such as scale, may hurt you.
BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2
Map<BigDecimal, String> map = new HashMap<>();
map.put(value1, "data");
System.out.println(map.get(value2));// null
In this case, you may want to stabilize scale with BigDecimal # stripTrailingZeros.
BigDecimal value1 = new BigDecimal("123.0"); // scale=1
BigDecimal value2 = new BigDecimal("123.00");// scale=2
Map<BigDecimal, String> map = new HashMap<>();
map.put(value1.stripTrailingZeros(), "data");
System.out.println(map.get(value2.stripTrailingZeros()));// data
BigDecimal # stripTrailingZeros has a bug up to java7.
JDK-6480539 : BigDecimal.stripTrailingZeros() has no effect on zero itself ("0.0")RoundingMode
RoundingMode is defined by ʻenum`, and there are various things such as" rounding up "," rounding down "," rounding to positive infinity ", and" rounding to negative infinity "in addition to" rounding ", so once javadoc is done. I think you should check it.
The following is a transcription of Rounding Mode javadoc.
CEILING This mode rounds to approach positive infinity. DOWN This mode rounds to approach 0. FLOOR It is a mode to round so as to approach negative infinity. HALF_DOWN Rounding mode to round to the "closest number" (rounded down if the numbers on both sides are equidistant). HALF_EVEN Rounding mode to round to the "closest number" (however, if the numbers on both sides are equidistant, round to the even side). HALF_UP Rounding mode to round to the "closest number" (however, if the numbers on both sides are equidistant, they are rounded up). UNNECESSARY Rounding mode that indicates that the result of the required operation is accurate and does not require rounding. UP This mode rounds away from 0.
RoundingMode are not availableDo not use the BigDecimal # ROUND_ ~ system and the methods that assume the use of these. (@Deprecated in Java 9)
There should be a pair of methods that use RoundingMode for each, so let's use these.
The method that became @Deprecated in 9 is a legacy of the 1.4 era.
However, when I usually google for "BigDecimal division", I'm desperate because all the pages that use BigDecimal.ROUND_HALF_UP come out.
Recommended Posts