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.
scale
There 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
HashMap
BigDecimal # 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