851.52K
Category: programming
Similar presentations:

Типы для времени и денег. BigDecimal

1.

IX. Типы для времени и денег
3. BigDecimal
1

2. Зачем нужен BigDecimal?

public
public class
class BigDecimalDemo
BigDecimalDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
double
double
double
double
double
double
AA
BB
CC
==
==
==
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
}}
}}
2.0;
2.0;
1.1;
1.1;
AA -- B;
B;
bigA
bigA
bigB
bigB
bigC
bigC
==
==
==
new
new BigDecimal("2.0");
BigDecimal("2.0");
new
new BigDecimal("1.1");
BigDecimal("1.1");
bigA.subtract(bigB);
bigA.subtract(bigB);
System.out.println("Using
System.out.println("Using
System.out.println("Using
System.out.println("Using
double
double "" ++
BigDecimal
BigDecimal
AA
""
++
++
"" -- "" ++ BB ++ "" == "" ++
bigA
bigA ++ "" -- "" ++ bigB
bigB
C);
C);
++ "" == "" ++ bigC);
bigC);
Using
Using double
double 2.0
2.0 -- 1.1
1.1 == 0.8999999999999999
0.8999999999999999
Using
Using BigDecimal
BigDecimal 2.0
2.0 -- 1.1
1.1 == 0.9
0.9
BigDecimal позволяет точно представлять
числа записанные в десятичной системе и
точно
выполнять
арифметические
операции.
2

3. Класс BigDecimal

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
private
intVal;
private volatile
volatile BigInteger
BigInteger intVal
intVal;
BigInteger
intVal
private
scale;
int scale
scale
private int
scale;
private
intCompact;
long
intCompact
private transient
transient long
long intCompact
intCompact;
INFLATED
final
static
long
Long.MIN_VALUE;
Long.MIN_VALUE
final static long INFLATED == Long.MIN_VALUE
Long.MIN_VALUE;
public
public int
int scale()
scale() {{
return
return scale;
scale;
}}
public
public BigDecimal
BigDecimal setScale(int
setScale(int newScale)
newScale)
public
public BigInteger
BigInteger unscaledValue()
unscaledValue() {{
return
return this.inflate();
this.inflate();
}}
}}
private
private BigInteger
BigInteger inflate()
inflate() {{
if
if (intVal
(intVal ==
== null)
null)
intVal
intVal == BigInteger.valueOf(intCompact);
BigInteger.valueOf(intCompact);
return
intVal;
return intVal;
}}
C
Класс BigDecimal позволяет представлять десятичные числа с произвольной точностью. Объекты класса
BigDecimal являются неизменными. BigDecimal включает мантиссу в виде BigInteger и десятичный порядок
в виде int. Десятичное число представляемое BigDecimal равно мантиссе поделённой на 10 в степени
десятичного порядка. (мантисса × 10^-порядок). Если значение мантиссы попадает в диапазон long за
исключением нижней границы может использоваться компактное представление мантиссы с помощью
long. С помощью методов unscaledValue и scale можно получить мантиссу и десятичный порядок. С
помощью метода precision() можно получить количество разрядов в мантиссе называемое разрядностью.
3

4. Класс BigDecimal

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
private
precision;
precision
private transient
transient int
int precision
precision;
}}
public
public int
int precision()
precision() {{
int
precision;
precision
int result
result == precision
precision;
if
if (result
(result ==
== 0)
0) {{
long
long ss == intCompact;
intCompact;
if
(s
!=
INFLATED)
if (s != INFLATED)
result
result == longDigitLength(s);
longDigitLength(s);
else
else
result
result == bigDigitLength(inflate());
bigDigitLength(inflate());
=
result;
precision
precision = result;
}}
return
return result;
result;
}}
4

5. Хранение BigDecimal

unscaledValue × 10(-scale)
2.00 = 200 × 10-2
unscaledValue: 200
scale: 2
precision: 3
2.0 = 20 × 10-1
unscaledValue: 20
scale: 1
precision: 2
Существует много представлений
для одного числа с помощью
BigDecimal.
5

6. Десятичный порядок, мантисса и разрядность

public
public class
class ScaleValuePrecisionDemo
ScaleValuePrecisionDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal big
big == new
new BigDecimal("123.456789");
BigDecimal("123.456789");
}}
}}
System.out.println("Big
System.out.println("Big decimal:
decimal: "" ++ big);
big);
System.out.println("Value:
"
+
big.unscaledValue());
System.out.println("Value: " + big.unscaledValue());
System.out.println("Scale:
System.out.println("Scale: "" ++ big.scale());
big.scale());
System.out.println("Precision:
System.out.println("Precision: "" ++ big.precision());
big.precision());
Big
Big decimal:
decimal: 123.456789
123.456789
Value:
Value: 123456789
123456789
Scale:
Scale: 66
Precision:
Precision: 99
6

7. “Изменение” десятичного порядка

public
public class
class SetScaleDemo
SetScaleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal big
big == new
new BigDecimal("200");
BigDecimal("200");
System.out.println("Big
System.out.println("Big decimal:
decimal: "" ++ big);
big);
System.out.println("Unscaled
value:
"
System.out.println("Unscaled value: " ++ big.unscaledValue());
big.unscaledValue());
System.out.println("Scale:
"
+
big.scale());
System.out.println("Scale: " + big.scale());
System.out.println("Precision:
System.out.println("Precision: "" ++ big.precision());
big.precision());
big
big == big.setScale(2);
big.setScale(2);
System.out.println("Big
System.out.println("Big decimal:
decimal: "" ++ big);
big);
System.out.println("Unscaled
System.out.println("Unscaled value:
value: "" ++ big.unscaledValue());
big.unscaledValue());
System.out.println("Scale:
System.out.println("Scale: "" ++ big.scale());
big.scale());
System.out.println("Precision:
System.out.println("Precision: "" ++ big.precision());
big.precision());
big
big == big.setScale(-2);
big.setScale(-2);
}}
}}
System.out.println("Big
System.out.println("Big decimal:
decimal: "" ++ big);
big);
System.out.println("Unscaled
System.out.println("Unscaled value:
value: "" ++ big.unscaledValue());
big.unscaledValue());
System.out.println("Scale:
System.out.println("Scale: "" ++ big.scale());
big.scale());
System.out.println("Precision:
"
System.out.println("Precision: " ++ big.precision());
big.precision());
7

8. “Изменение” десятичного порядка

Big
Big decimal:
decimal: 200
200
Unscaled
Unscaled value:
value: 200
200
Scale:
Scale: 00
Precision:
Precision: 33
Big
Big decimal:
decimal: 200.00
200.00
Unscaled
Unscaled value:
value: 20000
20000
Scale:
Scale: 22
Precision:
Precision: 55
Big
Big decimal:
decimal: 2E+2
2E+2
Unscaled
value:
Unscaled value: 22
Scale:
Scale: -2
-2
Precision:
Precision: 11
8

9. Неизменность BigDecimal

public
public class
class ImmutableDemo
ImmutableDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal initial
initial == new
new BigDecimal("0");
BigDecimal("0");
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
term1
term1
term2
term2
term3
term3
term4
term4
term5
term5
==
==
==
==
==
new
new
new
new
new
new
new
new
new
new
BigDecimal("0.001");
BigDecimal("0.001");
BigDecimal("0.002");
BigDecimal("0.002");
BigDecimal("0.003");
BigDecimal("0.003");
BigDecimal("0.004");
BigDecimal("0.004");
BigDecimal("0.005");
BigDecimal("0.005");
BigDecimal
BigDecimal result
System.out.println("Equal
System.out.println("Equal references
references ?? "" ++ (initial
(initial ==
== result));
result));
}}
}}
System.out.println("Initial
System.out.println("Initial value
value "" ++ initial);
initial);
System.out.println("Result
System.out.println("Result value
value "" ++ result);
result);
Equal
Equal references
references ?? false
false
Initial
value
0
Initial value 0
Result
Result value
value 0.015
0.015
9

10.

Проверка на равенство
10

11. Проверка на равенство

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
if
if
boolean
boolean equals(Object
equals(Object x)
x) {{
(!(x
(!(x instanceof
instanceof BigDecimal))
BigDecimal))
return
false;
return false;
BigDecimal
BigDecimal xDec
xDec == (BigDecimal)
(BigDecimal) x;
x;
if
if (x
(x ==
== this)
this)
return
return true;
true;
scale
scale
if
scale !=
scale ))
if (scale
(scale
!= xDec.scale
xDec.scale
return
return false;
false;
long
long ss == this.intCompact;
this.intCompact;
long
long xs
xs == xDec.intCompact;
xDec.intCompact;
if
if (s
(s !=
!= INFLATED)
INFLATED) {{
if
if (xs
(xs ==
== INFLATED)
INFLATED)
xs
=
compactValFor(xDec.intVal);
xs = compactValFor(xDec.intVal);
return
return xs
xs ==
== s;
s;
}} else
else if
if (xs
(xs !=
!= INFLATED)
INFLATED)
return
return xs
xs ==
== compactValFor(this.intVal);
compactValFor(this.intVal);
}}
}}
return
return this.inflate().equals(xDec.inflate());
this.inflate().equals(xDec.inflate());
Метод equals() сравнивает десятичный порядок и
мантиссу по отдельности поэтому различные
представления одного числа не равны.
11

12. Проверка на равенство

public
public class
class EqualsDemo
EqualsDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal bigA
bigA == new
new BigDecimal("2.00");
BigDecimal("2.00");
BigDecimal
BigDecimal bigB
bigB == new
new BigDecimal("2.0");
BigDecimal("2.0");
System.out.println("Big
System.out.println("Big decimal
decimal A:
A: "" ++ bigA
bigA ++ "" unscaled
unscaled value:
value: "" ++ bigA.unscaledValue()
bigA.unscaledValue() ++
"" scale:
scale: "" ++ bigA.scale()
bigA.scale() ++ "" precision:
precision: "" ++ bigA.precision());
bigA.precision());
System.out.println("Big
System.out.println("Big decimal
decimal B:
B: "" ++ bigB
bigB ++ "" unscaled
unscaled value:
value: "" ++ bigB.unscaledValue()
bigB.unscaledValue() ++
"" scale:
scale: "" ++ bigB.scale()
bigB.scale() ++ "" precision:
precision: "" ++ bigB.precision());
bigB.precision());
System.out.println("Are
System.out.println("Are AA and
and BB equal
equal ?? "" ++ bigA.equals(bigB));
bigA.equals(bigB));
bigA
bigA == bigA.stripTrailingZeros();
bigA.stripTrailingZeros();
System.out.println("Big
System.out.println("Big decimal
decimal A:
A: "" ++ bigA
bigA ++ "" unscaled
unscaled value:
value: "" ++ bigA.unscaledValue()
bigA.unscaledValue() ++
"" scale:
scale: "" ++ bigA.scale()
bigA.scale() ++ "" precision:
precision: "" ++ bigA.precision());
bigA.precision());
bigB
bigB == bigB.stripTrailingZeros();
bigB.stripTrailingZeros();
System.out.println("Big
System.out.println("Big decimal
decimal B:
B: "" ++ bigB
bigB ++ "" unscaled
unscaled value:
value: "" ++ bigB.unscaledValue()
bigB.unscaledValue() ++
"" scale:
scale: "" ++ bigB.scale()
bigB.scale() ++ "" precision:
precision: "" ++ bigB.precision());
bigB.precision());
}}
}}
System.out.println("Are
System.out.println("Are AA
System.out.println("Equal
System.out.println("Equal
and
and BB equal
equal
references?
references?
??
""
""
++
++ bigA.equals(bigB));
bigA.equals(bigB));
(bigA
(bigA ==
== bigB));
bigB));
Big
Big decimal
decimal A:
A: 2.00
2.00 unscaled
unscaled value:
value: 200
200 scale:
scale: 22 precision:
precision: 33
Big
Big decimal
decimal B:
B: 2.0
2.0 unscaled
unscaled value:
value: 20
20 scale:
scale: 11 precision:
precision: 22
Are
Are AA and
and BB equal
equal ?? false
false
Big
Big decimal
decimal A:
A: 22 unscaled
unscaled value:
value: 22 scale:
scale: 00 precision:
precision: 11
Big
Big decimal
decimal B:
B: 22 unscaled
unscaled value:
value: 22 scale:
scale: 00 precision:
precision: 11
Are
Are AA and
and BB equal
equal ?? true
true
Equal
references?
false
Equal references? false
12

13. Использование проверки на равенство

public
public class
class HashSetDemo
HashSetDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Set<BigDecimal>
Set<BigDecimal> set
set == new
new HashSet<BigDecimal>();
HashSet<BigDecimal>();
}}
}}
HashSet
HashSet
HashSet
HashSet
BigDecimal("2"));
BigDecimal("2"));
BigDecimal("2.0"));
BigDecimal("2.0"));
BigDecimal("2.00"));
BigDecimal("2.00"));
BigDecimal("2.000"));
BigDecimal("2.000"));
System.out.println("HashSet
System.out.println("HashSet
System.out.println("HashSet
System.out.println("HashSet
size:
size: "" ++
contents:
contents:
set.size());
set.size());
"" ++ set);
set);
size:
size: 44
contents:
contents: [2.00,
[2.00, 2.000,
2.000, 2,
2, 2.0]
2.0]
13

Сравнение
14

15. Сравнение

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public int
int compareTo(BigDecimal
compareTo(BigDecimal val)
val) {{
}}
if
if (scale
(scale ==
== val.scale)
val.scale) {{
long
long xs
xs == intCompact;
intCompact;
long
long ys
ys == val.intCompact;
val.intCompact;
if
if (xs
(xs !=
!= INFLATED
INFLATED &&
&& ys
ys !=
!= INFLATED)
INFLATED)
return
return xs
xs !=
!= ys
ys ?? ((xs
((xs >> ys)
ys) ?? 11 :: -1)
-1) :: 0;
0;
}}
int
int xsign
xsign == this.signum();
this.signum();
int
int ysign
ysign == val.signum();
val.signum();
if
if (xsign
(xsign !=
!= ysign)
ysign)
return
return (xsign
(xsign >> ysign)
ysign) ?? 11 :: -1;
-1;
if
(xsign
==
0)
if (xsign == 0)
return
return 0;
0;
int
int cmp
cmp == compareMagnitude(val);
compareMagnitude(val);
return
return (xsign
(xsign >> 0)
0) ?? cmp
cmp :: -cmp;
-cmp;
private
private int
int compareMagnitude(BigDecimal
compareMagnitude(BigDecimal val)
val) {{
...
...
}}
public
public BigDecimal
BigDecimal min(BigDecimal
min(BigDecimal val)
val) {{
return
return (compareTo(val)
(compareTo(val) <=
<= 00 ?? this
this :: val);
val);
}}
}}
public
public BigDecimal
BigDecimal max(BigDecimal
max(BigDecimal val)
val) {{
return
return (compareTo(val)
(compareTo(val) >=
>= 00 ?? this
this :: val);
val);
}}
В классе BigDecimal естественный порядок несовместим с
определением метода equals. С точки зрения метода
compareTo различные представления одного числа равны.
15

16. Сравнение

public
public class
class CompareDemo
CompareDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal bigA
bigA == new
new BigDecimal("2.00");
BigDecimal("2.00");
BigDecimal
BigDecimal bigB
bigB == new
new BigDecimal("2.0");
BigDecimal("2.0");
System.out.println("Big
System.out.println("Big decimal
decimal A:
A: "" ++ bigA
bigA ++ "" unscaled
unscaled value:
value: "" ++ bigA.unscaledValue()
bigA.unscaledValue() ++
"" scale:
scale: "" ++ bigA.scale()
bigA.scale() ++ "" precision:
precision: "" ++ bigA.precision());
bigA.precision());
System.out.println("Big
System.out.println("Big decimal
decimal B:
B: "" ++ bigB
bigB ++ "" unscaled
unscaled value:
value: "" ++ bigB.unscaledValue()
bigB.unscaledValue() ++
"" scale:
scale: "" ++ bigB.scale()
bigB.scale() ++ "" precision:
precision: "" ++ bigB.precision());
bigB.precision());
}}
Big
Big
Big
Big
Are
Are
}}
System.out.println("Are
System.out.println("Are AA and
and BB equal
equal ?? "" ++ (bigA.compareTo(bigB)
(bigA.compareTo(bigB) ==
== 0));
0));
decimal
decimal
decimal
decimal
AA and
and BB
A:
A: 2.00
2.00 unscaled
unscaled value:
value: 200
200 scale:
scale: 22 precision:
precision: 33
B:
B: 2.0
2.0 unscaled
unscaled value:
value: 20
20 scale:
scale: 11 precision:
precision: 22
equal
equal ?? true
true
16

17. Использование сравнения

public
public class
class TreeSetDemo
TreeSetDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Set<BigDecimal>
Set<BigDecimal> set
set == new
new TreeSet<BigDecimal>();
TreeSet<BigDecimal>();
}}
}}
TreeSet
TreeSet
TreeSet
TreeSet
BigDecimal("2"));
BigDecimal("2"));
BigDecimal("2.0"));
BigDecimal("2.0"));
BigDecimal("2.00"));
BigDecimal("2.00"));
BigDecimal("2.000"));
BigDecimal("2.000"));
System.out.println("TreeSet
System.out.println("TreeSet
System.out.println("TreeSet
System.out.println("TreeSet
size:
size: "" ++
contents:
contents:
set.size());
set.size());
"" ++ set);
set);
size:
size: 11
contents:
contents: [2]
[2]
17

18. Использование сравнения

public
public class
class TreeSetCompareDemo
TreeSetCompareDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Set<BigDecimal>
Set<BigDecimal> set
set == new
new TreeSet<BigDecimal>();
TreeSet<BigDecimal>();
}}
}}
TreeSet
TreeSet
TreeSet
TreeSet
BigDecimal("2"));
BigDecimal("2"));
BigDecimal("3.0"));
BigDecimal("3.0"));
BigDecimal("4.00"));
BigDecimal("4.00"));
BigDecimal("5.000"));
BigDecimal("5.000"));
BigDecimal("8.00"));
BigDecimal("8.00"));
BigDecimal("7.0"));
BigDecimal("7.0"));
BigDecimal("6.00"));
BigDecimal("6.00"));
BigDecimal("-1.0"));
BigDecimal("-1.0"));
BigDecimal("-2.00"));
BigDecimal("-2.00"));
BigDecimal("-3.0"));
BigDecimal("-3.0"));
BigDecimal("0.000"));
BigDecimal("0.000"));
System.out.println("TreeSet
System.out.println("TreeSet size:
size: "" ++ set.size());
set.size());
System.out.println("TreeSet
System.out.println("TreeSet contents:
contents: "" ++ set);
set);
size:
size: 11
11
contents:
contents: [-3.0,
[-3.0, -2.00,
-2.00, -1.0,
-1.0, 0.000,
0.000, 2,
2, 3.0,
3.0, 4.00,
4.00, 5.000,
5.000, 6.00,
6.00, 7.0,
7.0, 8.00]
8.00]
18

19.

Получение BigDecimal
19

20. Конструкторы BigDecimal

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
}}
BigDecimal(char[]
BigDecimal(char[] in,
in, int
int offset,
offset, int
int len)
len)
BigDecimal(char[]
BigDecimal(char[] in)
in)
BigDecimal(String
val)
BigDecimal(String val)
BigDecimal(double
double
val
BigDecimal(double
double val
val ))
BigDecimal(int
BigDecimal(int val)
val)
BigDecimal(long
BigDecimal(long val)
val)
BigDecimal(BigInteger
BigDecimal(BigInteger val)
val)
BigDecimal(BigInteger
BigDecimal(BigInteger unscaledVal,
unscaledVal, int
int scale)
scale)
BigDecimal(BigInteger
BigDecimal(BigInteger intVal,
intVal, long
long val,
val, int
int scale,
scale, int
int prec)
prec) {{
this.scale
this.scale == scale;
scale;
this.precision
this.precision == prec;
prec;
this.intCompact
this.intCompact == val;
val;
this.intVal
=
intVal;
this.intVal = intVal;
}}
Конструктор принимающий double в качестве
параметра использовать не следует из-за неточного
представления double.
20

21. Конструктор принимающий double

public
public class
class NoDoubleConstructorDemo
NoDoubleConstructorDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
}}
}}
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
BigDecimal(0.5));
BigDecimal(0.5));
BigDecimal(0.25));
BigDecimal(0.25));
BigDecimal(0.125));
BigDecimal(0.125));
BigDecimal(0.0625));
BigDecimal(0.0625));
BigDecimal(0.03125));
BigDecimal(0.03125));
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
BigDecimal(0.1));
BigDecimal(0.1));
BigDecimal(0.01));
BigDecimal(0.01));
BigDecimal(0.001));
BigDecimal(0.001));
BigDecimal(0.0001));
BigDecimal(0.0001));
BigDecimal(0.00001));
BigDecimal(0.00001));
0.5
0.5
0.25
0.25
0.125
0.125
0.0625
0.0625
0.03125
0.03125
0.1000000000000000055511151231257827021181583404541015625
0.1000000000000000055511151231257827021181583404541015625
0.01000000000000000020816681711721685132943093776702880859375
0.01000000000000000020816681711721685132943093776702880859375
0.001000000000000000020816681711721685132943093776702880859375
0.001000000000000000020816681711721685132943093776702880859375
0.000100000000000000004792173602385929598312941379845142364501953125
0.000100000000000000004792173602385929598312941379845142364501953125
0.000010000000000000000818030539140313095458623138256371021270751953125
0.000010000000000000000818030539140313095458623138256371021270751953125
21

22. Конструктор принимающий String

public
public class
class YesStringConstructorDemo
YesStringConstructorDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
}}
}}
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
BigDecimal("0.5"));
BigDecimal("0.5"));
BigDecimal("0.25"));
BigDecimal("0.25"));
BigDecimal("0.125"));
BigDecimal("0.125"));
BigDecimal("0.0625"));
BigDecimal("0.0625"));
BigDecimal("0.03125"));
BigDecimal("0.03125"));
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
System.out.println(new
BigDecimal("0.1"));
BigDecimal("0.1"));
BigDecimal("0.01"));
BigDecimal("0.01"));
BigDecimal("0.001"));
BigDecimal("0.001"));
BigDecimal("0.0001"));
BigDecimal("0.0001"));
BigDecimal("0.00001"));
BigDecimal("0.00001"));
0.5
0.5
0.25
0.25
0.125
0.125
0.0625
0.0625
0.03125
0.03125
0.1
0.1
0.01
0.01
0.001
0.001
0.0001
0.0001
0.00001
0.00001
22

23. Кеш экземпляров BigDecimal

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
private
private
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
new
};
};
}}
static
static final
final BigDecimal
BigDecimal zeroThroughTen[]
zeroThroughTen[] ==
BigDecimal(BigInteger.ZERO,
0,
BigDecimal(BigInteger.ZERO,
0, 0,
0, 1),
1),
BigDecimal(BigInteger.ONE,
1,
BigDecimal(BigInteger.ONE,
1, 0,
0, 1),
1),
BigDecimal(BigInteger.valueOf(2),
2,
BigDecimal(BigInteger.valueOf(2),
2, 0,
0,
BigDecimal(BigInteger.valueOf(3),
3,
BigDecimal(BigInteger.valueOf(3),
3, 0,
0,
BigDecimal(BigInteger.valueOf(4),
4,
0,
BigDecimal(BigInteger.valueOf(4),
4, 0,
BigDecimal(BigInteger.valueOf(5),
5,
BigDecimal(BigInteger.valueOf(5),
5, 0,
0,
BigDecimal(BigInteger.valueOf(6),
6,
BigDecimal(BigInteger.valueOf(6),
6, 0,
0,
BigDecimal(BigInteger.valueOf(7),
7,
BigDecimal(BigInteger.valueOf(7),
7, 0,
0,
BigDecimal(BigInteger.valueOf(8),
8,
BigDecimal(BigInteger.valueOf(8),
8, 0,
0,
BigDecimal(BigInteger.valueOf(9),
9,
0,
BigDecimal(BigInteger.valueOf(9),
9, 0,
BigDecimal(BigInteger.TEN,
10,
0,
BigDecimal(BigInteger.TEN,
10, 0, 2),
2),
{{
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
1),
private
private static
static final
final BigDecimal[]
BigDecimal[] ZERO_SCALED_BY
ZERO_SCALED_BY == {{
zeroThroughTen[0],
zeroThroughTen[0],
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 1,
1, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 2,
2, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 3,
3, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 4,
4, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 5,
5, 1),
1),
new
BigDecimal(BigInteger.ZERO,
0,
6,
1),
new BigDecimal(BigInteger.ZERO, 0, 6, 1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 7,
7, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 8,
8, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 9,
9, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 10,
10, 1),
1),
new
BigDecimal(BigInteger.ZERO,
0,
11,
1),
new BigDecimal(BigInteger.ZERO, 0, 11, 1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 12,
12, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 13,
13, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 14,
14, 1),
1),
new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, 15,
15, 1),
1),
};
};
23

24. Статические фабрики BigDecimal

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
if
if
}}
static
static BigDecimal
BigDecimal valueOf(long
valueOf(long unscaledVal,
unscaledVal, int
int scale)
scale) {{
(scale
(scale ==
== 0)
0)
return
valueOf(unscaledVal);
return valueOf(unscaledVal);
else
else if
if (unscaledVal
(unscaledVal ==
== 0)
0) {{
if
if (scale
(scale >> 00 &&
&& scale
scale << ZERO_SCALED_BY.length)
ZERO_SCALED_BY.length)
return
return ZERO_SCALED_BY[scale];
ZERO_SCALED_BY[scale];
else
else
return
return new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 0,
0, scale,
scale, 1);
1);
}}
return
return new
new BigDecimal(unscaledVal
BigDecimal(unscaledVal ==
== INFLATED
INFLATED ??
BigInteger.valueOf(unscaledVal)
BigInteger.valueOf(unscaledVal) :: null,
null,
unscaledVal,
unscaledVal, scale,
scale, 0);
0);
public
public static
static BigDecimal
BigDecimal valueOf(long
valueOf(long val)
val) {{
if
if (val
(val >=
>= 00 &&
&& val
val << zeroThroughTen.length)
zeroThroughTen.length)
return
return zeroThroughTen[(int)val];
zeroThroughTen[(int)val];
else
if
(val
else if (val !=
!= INFLATED)
INFLATED)
return
new
BigDecimal(null,
return new BigDecimal(null, val,
val, 0,
0, 0);
0);
return
return new
new BigDecimal(BigInteger.valueOf(val),
BigDecimal(BigInteger.valueOf(val), val,
val, 0,
0, 0);
0);
}}
}}
public
public static
static BigDecimal
BigDecimal valueOf(double
valueOf(double val)
val) {{
return
return new
new BigDecimal(Double.toString(val));
BigDecimal(Double.toString(val));
}}
24

25. Кеширование целых чисел 0 - 10

public
public class
class CachingDemo
CachingDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal ii == new
new BigDecimal(10);
BigDecimal(10);
BigDecimal
BigDecimal jj == BigDecimal.valueOf(10);
BigDecimal.valueOf(10);
System.out.println("i
System.out.println("i == "" ++ ii ++ ",
", jj == "" ++ jj ++ ",
", i==j
i==j is
is "" ++ (i
(i ==
== j));
j));
BigDecimal
BigDecimal kk == BigDecimal.valueOf(10);
BigDecimal.valueOf(10);
BigDecimal
BigDecimal ll == BigDecimal.valueOf(10);
BigDecimal.valueOf(10);
System.out.println("k
System.out.println("k == "" ++ kk ++ ",
", ll == "" ++ ll ++ ",
", k==l
k==l is
is "" ++ (k
(k ==
== l));
l));
BigDecimal
BigDecimal mm == BigDecimal.valueOf(11);
BigDecimal.valueOf(11);
BigDecimal
BigDecimal nn == BigDecimal.valueOf(11);
BigDecimal.valueOf(11);
}}
}}
ii
kk
mm
==
==
==
10,
10,
10,
10,
11,
11,
System.out.println("m
System.out.println("m == "" ++ mm ++ ",
", nn == "" ++ nn ++ ",
", m==n
m==n is
is "" ++ (m
(m ==
== n));
n));
jj
ll
nn
==
==
==
10,
10,
10,
10,
11,
11,
i==j
i==j
k==l
k==l
m==n
m==n
is
is
is
is
is
is
false
false
true
true
false
false
25

26. Кеширование нулей

public
public class
class CachingZeroDemo
CachingZeroDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal ii == new
new BigDecimal(BigInteger.ZERO,
BigDecimal(BigInteger.ZERO, 15);
15);
BigDecimal
BigDecimal jj == BigDecimal.valueOf(0,
BigDecimal.valueOf(0, 15);
15);
System.out.println("i
System.out.println("i == "" ++ ii ++ ",
", jj == "" ++ jj ++ ",
", i==j
i==j is
is "" ++ (i
(i ==
== j));
j));
BigDecimal
BigDecimal kk == BigDecimal.valueOf(0,
BigDecimal.valueOf(0, 15);
15);
BigDecimal
BigDecimal ll == BigDecimal.valueOf(0,
BigDecimal.valueOf(0, 15);
15);
System.out.println("k
System.out.println("k == "" ++ kk ++ ",
", ll == "" ++ ll ++ ",
", k==l
k==l is
is "" ++ (k
(k ==
== l));
l));
BigDecimal
BigDecimal mm == BigDecimal.valueOf(0,
BigDecimal.valueOf(0, 16);
16);
BigDecimal
BigDecimal nn == BigDecimal.valueOf(0,
BigDecimal.valueOf(0, 16);
16);
}}
}}
ii
kk
mm
==
==
==
System.out.println("m
System.out.println("m == "" ++ mm ++ ",
", nn == "" ++ nn ++ ",
", m==n
m==n is
is "" ++ (m
(m ==
== n));
n));
0E-15,
0E-15,
0E-15,
0E-15,
0E-16,
0E-16,
jj
ll
nn
==
==
==
0E-15,
0E-15,
0E-15,
0E-15,
0E-16,
0E-16,
i==j
i==j
k==l
k==l
m==n
m==n
is
is
is
is
is
is
false
false
true
true
false
false
26

27.

Точные арифметические операции
27

28. Точные арифметические операции

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
public
public
public
public
public
public
public
public
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
augend)
subtract(BigDecimal
subtract(BigDecimal subtrahend)
subtrahend)
multiply(BigDecimal
multiply(BigDecimal multiplicand)
multiplicand)
divide(BigDecimal
divide(BigDecimal divisor)
divisor)
setScale(int
newScale)
setScale(int newScale)
}}
C
Методы add, subtract и multiply всегда возвращают точный результат. Десятичный порядок
результата равен так называемому предпочтительному порядку. Метод divide может выбросить
исключение ArithmeticException если точный результат не может быть представлен используя
конечное число разрядов, например при делении 1 на 3. Десятичный порядок результата может
быть больше предпочтительного порядка если это необходимо, например при делении 1 на 32.
Метод setScale возвращает BigDecimal с заданным десятичным порядком и с тем же численным
значением что и исходный BigDecimal. Этот метод выбрасывает исключение ArithmeticException
если операция изменения десятичного порядка требует округления.
28

29. Предпочтительный порядок

Операция
Порядок
Порядок
Предпочтительный
порядок
A.scale()
B.scale()
Max(A.scale(),B.scale())
A.subtract(B)
A.scale()
B.scale()
Max(A.scale(),B.scale())
A.multiply(B)
A.scale()
B.scale()
A.scale()+B.scale()
A.divide(B)
A.scale()
B.scale()
A.scale()-B.scale()
29

30. Точные арифметические операции

public
public class
class PreciseArithmeticDemo
PreciseArithmeticDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal
BigDecimal
BigDecimal
aa
bb
==
==
new
new
new
new
BigDecimal("0.002");
BigDecimal("0.002");
BigDecimal("0.001");
BigDecimal("0.001");
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
++
++
++
++
""
""
""
""
++
-**
//
""
""
""
""
++
++
++
++
bb
bb
bb
bb
++
++
++
++
""
""
""
""
==
==
==
==
""
""
""
""
++
++
++
++
a.subtract(b));
a.subtract(b));
a.multiply(b));
a.multiply(b));
a.divide(b));
a.divide(b));
++
++
++
++
bb
bb
bb
bb
++
++
++
++
""
""
""
""
==
==
==
==
""
""
""
""
++
++
++
++
);
a.subtract(b));
a.subtract(b));
a.multiply(b));
a.multiply(b));
a.divide(b));
a.divide(b));
System.out.println();
System.out.println();
aa
bb
}}
==
==
BigDecimal("100");
BigDecimal("100");
BigDecimal("0.01");
BigDecimal("0.01");
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
System.out.println(a
}}
0.002
0.002
0.002
0.002
0.002
0.002
0.002
0.002
++
-**
//
100
100
100
100
100
100
100
100
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
++
-**
//
new
new
new
new
0.001
0.001
0.001
0.001
0.001
0.001
0.001
0.001
==
==
==
==
==
==
==
==
++
++
++
++
""
""
""
""
++
-**
//
""
""
""
""
0.003
0.003
0.001
0.001
0.000002
0.000002
22
100.01
100.01
99.99
99.99
1.00
1.00
1.00E+4
1.00E+4
30

31. Точное деление

public
public class
class PreciseDivisionDemo
PreciseDivisionDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal aa == new
new BigDecimal("1");
BigDecimal("1");
BigDecimal
b
=
new
BigDecimal("32");
BigDecimal b = new BigDecimal("32");
System.out.println(a
System.out.println(a ++ "" // "" ++ bb ++ "" == "" ++ a.divide(b));
a.divide(b));
System.out.println();
System.out.println();
aa == new
new BigDecimal("1");
BigDecimal("1");
bb == new
new BigDecimal("3");
BigDecimal("3");
}}
}}
System.out.println(a
System.out.println(a ++ "" // "" ++ bb ++ "" == "" ++ a.divide(b));
a.divide(b));
11 // 32
32 == 0.03125
0.03125
Exception
Exception in
"main" java.lang.ArithmeticException:
java.lang.ArithmeticException: Non-terminating
Non-terminating decimal
decimal expansion;
expansion; no
no exact
exact
representable
representable decimal
decimal result.
result.
at
at java.math.BigDecimal.divide(Unknown
java.math.BigDecimal.divide(Unknown Source)
Source)
at
at bigdecimal.PreciseDivisionDemo.main(PreciseDivisionDemo.java:19)
bigdecimal.PreciseDivisionDemo.main(PreciseDivisionDemo.java:19)
31

32. Точное “изменение” десятичного порядка

public
public class
class ScaleDemo
ScaleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal aa == new
new BigDecimal("2.10000");
BigDecimal("2.10000");
}}
}}
System.out.println(a);
System.out.println(a);
System.out.println(a.setScale(4));
System.out.println(a.setScale(4));
System.out.println(a.setScale(3));
System.out.println(a.setScale(3));
System.out.println(a.setScale(2));
System.out.println(a.setScale(2));
System.out.println(a.setScale(1));
System.out.println(a.setScale(1));
System.out.println(a.setScale(0));
System.out.println(a.setScale(0));
2.10000
2.10000
2.1000
2.1000
2.100
2.100
2.10
2.10
2.1
2.1
Exception
Exception in
"main" java.lang.ArithmeticException:
java.lang.ArithmeticException: Rounding
Rounding necessary
necessary
at
java.math.BigDecimal.divideAndRound(Unknown
Source)
at java.math.BigDecimal.divideAndRound(Unknown Source)
at
at java.math.BigDecimal.setScale(Unknown
java.math.BigDecimal.setScale(Unknown Source)
Source)
at
at java.math.BigDecimal.setScale(Unknown
java.math.BigDecimal.setScale(Unknown Source)
Source)
at
at bigdecimal.ScaleDemo.main(ScaleDemo.java:17)
bigdecimal.ScaleDemo.main(ScaleDemo.java:17)
32

33.

Арифметические операции c контекстом
33

34. Класс MathContext

public
public final
final class
class MathContext
MathContext implements
implements Serializable
Serializable {{
final
int
precision;
final int
int precision
precision;
precision
final
RoundingMode
roundingMode;
RoundingMode
roundingMode
final RoundingMode
RoundingMode roundingMode
roundingMode;
public
public MathContext(int
MathContext(int
this(setPrecision,
this(setPrecision,
return;
return;
}}
setPrecision)
setPrecision) {{
DEFAULT_ROUNDINGMODE);
DEFAULT_ROUNDINGMODE);
public
public MathContext(int
MathContext(int setPrecision,
setPrecision, RoundingMode
RoundingMode setRoundingMode)
setRoundingMode) {{
if
if (setPrecision
(setPrecision << MIN_DIGITS)
MIN_DIGITS)
throw
throw new
new IllegalArgumentException("Digits
IllegalArgumentException("Digits << 0");
0");
if
if (setRoundingMode
(setRoundingMode ==
== null)
null)
throw
new
NullPointerException("null
throw new NullPointerException("null RoundingMode");
RoundingMode");
}}
precision
precision == setPrecision;
setPrecision;
roundingMode
roundingMode == setRoundingMode;
setRoundingMode;
return;
return;
public
public int
int getPrecision()
getPrecision() {{
return
return precision;
precision;
}}
}}
public
public RoundingMode
RoundingMode getRoundingMode()
getRoundingMode() {{
return
return roundingMode;
roundingMode;
}}
C
Класс MathContext позволяет задавать разрядность
результата и способ округления. Для задания
способа округления используется перечисление
RoundingMode.
34

35. Перечисление RoundingMode

public
public enum
enum RoundingMode
RoundingMode {{
UP(BigDecimal.ROUND_UP),
UP(BigDecimal.ROUND_UP),
DOWN(BigDecimal.ROUND_DOWN),
DOWN(BigDecimal.ROUND_DOWN),
CEILING(BigDecimal.ROUND_CEILING),
CEILING(BigDecimal.ROUND_CEILING),
FLOOR(BigDecimal.ROUND_FLOOR),
FLOOR(BigDecimal.ROUND_FLOOR),
HALF_UP(BigDecimal.ROUND_HALF_UP),
HALF_UP(BigDecimal.ROUND_HALF_UP),
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
final
final int
int oldMode;
oldMode;
}}
private
private RoundingMode(int
RoundingMode(int oldMode)
oldMode) {{
this.oldMode
this.oldMode == oldMode;
oldMode;
}}
public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
}}
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
static
static
static
static
static
static
static
static
static
static
static
static
static
static
static
static
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
ROUND_UP
ROUND_UP ==
ROUND_DOWN
ROUND_DOWN ==
ROUND_CEILING
ROUND_CEILING ==
ROUND_FLOOR
ROUND_FLOOR ==
ROUND_HALF_UP
ROUND_HALF_UP ==
ROUND_HALF_DOWN
ROUND_HALF_DOWN ==
ROUND_HALF_EVEN
ROUND_HALF_EVEN ==
ROUND_UNNECESSARY
ROUND_UNNECESSARY ==
0;
0;
1;
1;
2;
2;
3;
3;
4;
4;
5;
5;
6;
6;
7;
7;
public
public BigDecimal
BigDecimal divide(BigDecimal
divide(BigDecimal divisor,
divisor, int
int roundingMode)
roundingMode)
C
Перечисление RoundingMode задаёт способ
округления
арифметических
операций
с
контекстом. Позволяет обходиться без статических
констант из класса BigDecimal.
35

36. Перечисление RoundingMode

Способ округления
Описание
UP
округление от нуля, к большему по модулю целому значению
DOWN
округление к нулю, к меньшему по модулю целому значению
CEILING
FLOOR
округление в сторону большего целого
округление к меньшему целому
HALF_UP
округление к ближайшему целому, среднее значение округляется к большему целому
HALF_DOWN
округление к ближайшему целому, среднее значение округляется к меньшему целому
HALF_EVEN
UNNECESSARY
округление к ближайшему целому, среднее значение округляется к четному числу
предполагается, что результат будет целым, и округление не понадобится в противном
случае будет выброшено исключение
36

37. Перечисление RoundingMode

Результат округления используя различные способы округления
Число
UP
DOWN
CEILING
FLOOR
HALF_UP HALF_DOWN HALF_EVEN
5.5
6
5
6
5
6
5
6
ArithmeticException
2.5
3
2
3
2
3
2
2
ArithmeticException
1.6
2
1
2
1
2
2
2
ArithmeticException
1.1
2
1
2
1
1
1
1
ArithmeticException
1.0
1
1
1
1
1
1
1
1
-1.0
-1
-1
-1
-1
-1
-1
-1
-1
-1.1
-2
-1
-1
-2
-1
-1
-1
ArithmeticException
-1.6
-2
-1
-1
-2
-2
-2
-2
ArithmeticException
-2.5
-3
-2
-2
-3
-3
-2
-2
ArithmeticException
-5.5
-6
-5
-5
-6
-6
-5
-6
ArithmeticException
Если
используется
способ
округления
UNNECESSARY, а округление необходимо будет
выброшено исключение ArithmeticException.
UNNECESSARY
37

38. Арифметические операции c контекстом

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
public
public
public
public
public
public
}}
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
BigDecimal
augend, MathContext
MathContext mc)
mc)
subtract(BigDecimal
subtract(BigDecimal subtrahend,
subtrahend, MathContext
MathContext mc)
mc)
multiply(BigDecimal
multiply(BigDecimal multiplicand,
multiplicand, MathContext
MathContext mc)
mc)
divide(BigDecimal
divisor,
MathContext
mc)
divide(BigDecimal divisor, MathContext mc)
public
public BigDecimal
BigDecimal round(MathContext
round(MathContext mc)
mc)
C
Для всех арифметических операций, результат будет таким, как будто сначала был получен
точный промежуточный результат, а потом он был округлён до указанного числа разрядов
заданных разрядностью (если необходимо), используя заданный способ округления. Разрядность
и способ округления задаются с помощью MathContext.
38

39. Арифметические операции c контекстом

public
public class
class ContextArithmeticDemo
ContextArithmeticDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal
BigDecimal
BigDecimal
}}
}}
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
2.00000
aa
bb
==
==
new
new
new
new
BigDecimal("2.00000");
BigDecimal("2.00000");
BigDecimal("3.0");
BigDecimal("3.0");
for
for (int
(int ii == 1;
1; ii << 10;
10; i++)
i++) {{
MathContext
MathContext context
context == new
new MathContext(i,
MathContext(i, RoundingMode.HALF_UP);
RoundingMode.HALF_UP);
System.out.println(a
System.out.println(a ++ "" // "" ++ bb ++ "" == "" ++ a.divide(b,
a.divide(b, context));
context));
}}
//
//
//
//
//
//
//
//
//
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
3.0
==
==
==
==
==
==
==
==
==
0.7
0.7
0.67
0.67
0.667
0.667
0.6667
0.6667
0.66667
0.66667
0.666667
0.666667
0.6666667
0.6666667
0.66666667
0.66666667
0.666666667
0.666666667
39

40.

“Старые” арифметические операции
40

41. “Старые” арифметические операции

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
static
static
static
static
static
static
static
static
static
static
static
static
static
static
static
static
public
public
public
public
BigDecimal
BigDecimal
BigDecimal
BigDecimal
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
ROUND_UP
ROUND_UP ==
ROUND_DOWN
ROUND_DOWN ==
ROUND_CEILING
ROUND_CEILING ==
ROUND_FLOOR
ROUND_FLOOR ==
ROUND_HALF_UP
ROUND_HALF_UP ==
ROUND_HALF_DOWN
ROUND_HALF_DOWN ==
ROUND_HALF_EVEN
ROUND_HALF_EVEN ==
ROUND_UNNECESSARY
ROUND_UNNECESSARY ==
divide(BigDecimal
divide(BigDecimal divisor,
divisor,
setScale(int
newScale,
setScale(int newScale, int
int
0;
0;
1;
1;
2;
2;
3;
3;
4;
4;
5;
5;
6;
6;
7;
7;
int
int scale,
scale, int
int roundingMode)
roundingMode)
roundingMode)
roundingMode)
}}
C
До появления перечислений в J2SE 5.0 для задания способа округления использовался набор
статических целочисленных констант. В классе BigDecimal есть перегруженные варианты
методов использующие эти константы. Кроме способа округления задаётся десятичный порядок.
41

42. “Старые” арифметические операции

public
public class
class OldDivideDemo
OldDivideDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal
BigDecimal
BigDecimal
}}
aa
bb
==
==
new
new
new
new
BigDecimal("2.00000");
BigDecimal("2.00000");
BigDecimal("3.0");
BigDecimal("3.0");
for
for (int
(int ii == 1;
1; ii << 10;
10; i++)
i++)
System.out.println(a
System.out.println(a ++ ""
++ a.divide(b,
a.divide(b, i,
i,
}}
{{
// "" ++ bb ++ "" == ""
BigDecimal.ROUND_HALF_UP));
BigDecimal.ROUND_HALF_UP));
for
for (int
(int ii == 1;
1; ii << 10;
10; i++)
i++)
System.out.println(a
System.out.println(a ++ ""
++ a.divide(b,
a.divide(b, i,
i,
}}
{{
// "" ++ bb ++ "" == ""
BigDecimal.ROUND_UNNECESSARY));
BigDecimal.ROUND_UNNECESSARY));
}}
2.00000
2.00000 // 3.0
3.0 == 0.7
0.7
2.00000
2.00000 // 3.0
3.0 == 0.67
0.67
2.00000
/
3.0
=
0.667
2.00000 / 3.0 = 0.667
2.00000
2.00000 // 3.0
3.0 == 0.6667
0.6667
2.00000
2.00000 // 3.0
3.0 == 0.66667
0.66667
2.00000
2.00000 // 3.0
3.0 == 0.666667
0.666667
2.00000
2.00000 // 3.0
3.0 == 0.6666667
0.6666667
2.00000
/
3.0
=
0.66666667
2.00000 / 3.0 = 0.66666667
2.00000
2.00000 // 3.0
3.0 == 0.666666667
0.666666667
Exception
Exception in
"main" java.lang.ArithmeticException:
java.lang.ArithmeticException: Rounding
Rounding necessary
necessary
at
at java.math.BigDecimal.divideAndRound(BigDecimal.java:1439)
java.math.BigDecimal.divideAndRound(BigDecimal.java:1439)
at
at java.math.BigDecimal.divide(BigDecimal.java:1385)
java.math.BigDecimal.divide(BigDecimal.java:1385)
at
bigdecimal.OldDivideDemo.main(OldDivideDemo.java:21)
at bigdecimal.OldDivideDemo.main(OldDivideDemo.java:21)
42

43. “Старые” арифметические операции

public
public class
class OldSetScaleDemo
OldSetScaleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal aa == new
new BigDecimal("2.333333");
BigDecimal("2.333333");
}}
}}
System.out.println(a);
System.out.println(a);
System.out.println(a.setScale(4,
System.out.println(a.setScale(4,
System.out.println(a.setScale(3,
System.out.println(a.setScale(3,
System.out.println(a.setScale(2,
System.out.println(a.setScale(2,
System.out.println(a.setScale(1,
System.out.println(a.setScale(1,
System.out.println(a.setScale(0,
System.out.println(a.setScale(0,
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
BigDecimal.ROUND_DOWN));
2.333333
2.333333
2.3333
2.3333
2.333
2.333
2.33
2.33
2.3
2.3
22
43

44.

Преобразования к другим типам
44

45. Преобразования к другим типам

public
public abstract
abstract class
class Number
Number implements
implements java.io.Serializable
java.io.Serializable {{
public
public
public
public
abstract
abstract
abstract
abstract
int
int intValue();
intValue();
long
long longValue();
longValue();
public
public abstract
abstract float
float floatValue();
floatValue();
public
abstract
double
public abstract double doubleValue();
doubleValue();
public
public byte
byte byteValue()
byteValue() {{
return
return (byte)intValue();
(byte)intValue();
}}
}}
public
public short
short shortValue()
shortValue() {{
return
return (short)intValue();
(short)intValue();
}}
45

46. Преобразования к BigInteger

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public BigInteger
BigInteger toBigInteger()
toBigInteger() {{
return
return this.setScale(0,
this.setScale(0, ROUND_DOWN).inflate();
ROUND_DOWN).inflate();
}}
}}
public
public BigInteger
BigInteger toBigIntegerExact()
toBigIntegerExact() {{
return
return this.setScale(0,
this.setScale(0, ROUND_UNNECESSARY).inflate();
ROUND_UNNECESSARY).inflate();
}}
46

47. Преобразования к BigInteger

public
public class
class ToBigIntegerDemo
ToBigIntegerDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal decA
decA == new
new BigDecimal("123.456789");
BigDecimal("123.456789");
System.out.println("BigDecimal
System.out.println("BigDecimal value
value is:
is: "" ++ decA);
decA);
BigInteger
BigInteger intA
intA == decA.toBigInteger();
decA.toBigInteger();
System.out.println("Converted
System.out.println("Converted BigInteger
BigInteger value
value is:
is: "" ++ intA);
intA);
}}
}}
intA
intA == decA.toBigIntegerExact();
decA.toBigIntegerExact();
System.out.println("Converted
System.out.println("Converted BigInteger
BigInteger using
using exact
exact conversion
conversion value
value is:
is: "" ++ intA);
intA);
BigDecimal
BigDecimal value
value is:
is: 123.456789
123.456789
Converted
BigInteger
value
Converted BigInteger value is:
is: 123
123
Exception
in
"main"
java.lang.ArithmeticException:
Exception in thread "main" java.lang.ArithmeticException: Rounding
Rounding necessary
necessary
at
at java.math.BigDecimal.divideAndRound(Unknown
java.math.BigDecimal.divideAndRound(Unknown Source)
Source)
at
at java.math.BigDecimal.setScale(Unknown
java.math.BigDecimal.setScale(Unknown Source)
Source)
at
at java.math.BigDecimal.toBigIntegerExact(Unknown
java.math.BigDecimal.toBigIntegerExact(Unknown Source)
Source)
at
bigdecimal.ConversionDemo.main(ConversionDemo.java:16)
at bigdecimal.ConversionDemo.main(ConversionDemo.java:16)
47

48. Преобразования к примитивным типам

public
public class
class BigDecimal
BigDecimal extends
extends Number
Number implements
implements Comparable<BigDecimal>
Comparable<BigDecimal> {{
public
public float
float floatValue(){
floatValue(){
if
if (scale
(scale ==
== 00 &&
&& intCompact
intCompact !=
!= INFLATED)
INFLATED)
return
(float)intCompact;
return (float)intCompact;
return
return Float.parseFloat(this.toString());
Float.parseFloat(this.toString());
}}
public
public
if
if
}}
double
double doubleValue(){
doubleValue(){
(scale
==
(scale == 00 &&
&& intCompact
intCompact !=
!= INFLATED)
INFLATED)
return
(double)intCompact;
return (double)intCompact;
return
return Double.parseDouble(this.toString());
Double.parseDouble(this.toString());
public
public long
long longValue(){
longValue(){
return
(intCompact
return (intCompact !=
!= INFLATED
INFLATED &&
&& scale
scale ==
== 0)
0) ?? intCompact
intCompact :: toBigInteger().longValue();
toBigInteger().longValue();
}}
public
public int
int intValue()
intValue() {{
return
return (intCompact
(intCompact !=
!= INFLATED
INFLATED &&
&& scale
scale ==
== 0)
0) ?? (int)intCompact
(int)intCompact :: toBigInteger().intValue();
toBigInteger().intValue();
}}
}}
public
public
public
public
public
public
public
public
long
long longValueExact()
longValueExact()
int
int intValueExact()
intValueExact()
short
short shortValueExact()
shortValueExact()
byte
byteValueExact()
byte byteValueExact()
48

49. Преобразования к числам с плавающей точкой

public
public class
class ToDoubleDemo
ToDoubleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal decA
decA == new
new BigDecimal("1.234567890123456789");
BigDecimal("1.234567890123456789");
System.out.println("BigDecimal
System.out.println("BigDecimal value
value is:
is: "" ++ decA);
decA);
double
double doubleA
doubleA == decA.doubleValue();
decA.doubleValue();
System.out.println("Converted
System.out.println("Converted double
double value
value is:
is: "" ++ doubleA);
doubleA);
}}
}}
float
float floatA
floatA == decA.floatValue();
decA.floatValue();
System.out.println("Converted
System.out.println("Converted float
float value
value is:
is: "" ++ floatA);
floatA);
BigDecimal
BigDecimal value
value is:
is: 1.234567890123456789
1.234567890123456789
Converted
double
value
Converted double value is:
is: 1.2345678901234567
1.2345678901234567
Converted
Converted float
float value
value is:
is: 1.2345679
1.2345679
49

50. Преобразования к целым числам

public
public class
class ToIntDemo
ToIntDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
BigDecimal
BigDecimal decA
decA == new
new BigDecimal("1234567890123456789.0123456789");
BigDecimal("1234567890123456789.0123456789");
System.out.println("BigDecimal
System.out.println("BigDecimal value
value is:
is: "" ++ decA);
decA);
long
long longA
longA == decA.longValue();
decA.longValue();
System.out.println("Converted
System.out.println("Converted long
long value
value is:
is: "" ++ longA);
longA);
}}
}}
longA
longA == decA.longValueExact();
decA.longValueExact();
System.out.println("Converted
System.out.println("Converted long
long value
value using
using exact
exact conversion
conversion is:
is: "" ++ longA);
longA);
BigDecimal
BigDecimal value
value is:
is: 1234567890123456789.0123456789
1234567890123456789.0123456789
Converted
long
value
is:
Converted long value is: 1234567890123456789
1234567890123456789
Exception
Exception in
"main" java.lang.ArithmeticException:
java.lang.ArithmeticException: Rounding
Rounding necessary
necessary
at
at java.math.BigDecimal.divideAndRound(Unknown
java.math.BigDecimal.divideAndRound(Unknown Source)
Source)
at
at java.math.BigDecimal.setScale(Unknown
java.math.BigDecimal.setScale(Unknown Source)
Source)
at
java.math.BigDecimal.longValueExact(Unknown
at java.math.BigDecimal.longValueExact(Unknown Source)
Source)
at
bigdecimal.ToIntDemo.main(ToIntDemo.java:16)
at bigdecimal.ToIntDemo.main(ToIntDemo.java:16)
50