JAVA PAGRINDAI DETALIAU

Java BigDecimal

BigDecimal yra klasė tiksliems dešimtainiams skaičiavimams. Ji ypač naudinga skaičiuojant pinigus, palūkanas ar kitas reikšmes, kurių negalima netiksliai suapvalinti.

Kodėl ne visada pakanka double?

double skaičius saugo dvejetaine forma. Kai kurių mums paprastų dešimtainių trupmenų, pavyzdžiui, 0.1, dvejetaine sistema tiksliai užrašyti neįmanoma:

double pirmaKaina = 0.1;
double antraKaina = 0.2;

System.out.println(pirmaKaina + antraKaina);
Konsolės rezultatas

0.30000000000000004

Kasdieniam matavimui toks labai mažas skirtumas dažnai netrukdo. Tačiau pinigų skaičiavimuose daug operacijų gali sukaupti pastebimą paklaidą.

Tikslus skaičiavimas su BigDecimal

import java.math.BigDecimal;

BigDecimal pirmaKaina = new BigDecimal("0.10");
BigDecimal antraKaina = new BigDecimal("0.20");
BigDecimal suma = pirmaKaina.add(antraKaina);

System.out.println(suma);
Konsolės rezultatas

0.30

  1. Importuojama klasė java.math.BigDecimal.
  2. Skaičiai konstruktoriui perduodami kaip tekstas, todėl jų dešimtainė reikšmė išlieka tiksli.
  3. Sudėčiai naudojamas metodas add(), o ne operatorius +.
  4. Rezultatas išsaugomas naujame BigDecimal objekte.

Kaip saugiai sukurti BigDecimal?

BigDecimal isTeksto = new BigDecimal("19.99");
BigDecimal isSveikojo = BigDecimal.valueOf(12);
BigDecimal isDouble = BigDecimal.valueOf(0.1);

// Venk: new BigDecimal(0.1)
  • new BigDecimal("19.99") tinka, kai tiksli reikšmė gaunama kaip tekstas.
  • BigDecimal.valueOf(12) patogu sveikajam skaičiui.
  • BigDecimal.valueOf(0.1) naudoja nuspėjamą double tekstinę išraišką.
  • new BigDecimal(0.1) perima jau egzistuojančią dvejetainio double paklaidą, todėl jo geriau vengti.
Pinigams rinkis tekstą.

Jei kode tiksliai žinai kainą, aiškiausias užrašymas dažniausiai yra new BigDecimal("9.99").

Pagrindiniai veiksmai

Kiekviena žemiau esanti operacija pradedama nuo tos pačios pradinės kaina reikšmės 12.50. Operacijų rezultatai saugomi atskiruose kintamuosiuose, todėl vienas skaičiavimas netampa kito pradžia.

BigDecimal kaina = new BigDecimal("12.50");
BigDecimal kiekis = new BigDecimal("3");

BigDecimal suma = kaina.add(new BigDecimal("2.00")); // 12.50 + 2.00 = 14.50
BigDecimal skirtumas = kaina.subtract(new BigDecimal("1.50")); // 12.50 - 1.50 = 11.00
BigDecimal bendraKaina = kaina.multiply(kiekis); // 12.50 × 3 = 37.50

System.out.println(suma); // Išspausdina 14.50
System.out.println(skirtumas); // Išspausdina 11.00
System.out.println(bendraKaina); // Išspausdina 37.50
Konsolės rezultatas

14.50
11.00
37.50

BigDecimal aritmetikos metodai
VeiksmasMetodas
Sudėtisadd()
Atimtissubtract()
Daugybamultiply()
Dalybadivide()

BigDecimal objektas yra nekeičiamas

BigDecimal likutis = new BigDecimal("10.00");

likutis.add(new BigDecimal("5.00"));
System.out.println(likutis);

likutis = likutis.add(new BigDecimal("5.00"));
System.out.println(likutis);
Konsolės rezultatas

10.00
15.00

Pirmasis add() sukuria naują rezultatą, bet jis niekur neišsaugomas. Pradinis objektas nepasikeičia. Antrojo veiksmo rezultatas priskiriamas atgal kintamajam, todėl vėliau matome 15.00.

Dalyba ir apvalinimas

Ne kiekviena dalyba turi baigtinį dešimtainį rezultatą. Dalijant 10 iš 3, reikia nurodyti, kiek skaitmenų palikti ir kaip apvalinti:

import java.math.RoundingMode;

BigDecimal suma = new BigDecimal("10.00");
BigDecimal zmoniu = new BigDecimal("3");

BigDecimal dalis = suma.divide(zmoniu, 2, RoundingMode.HALF_UP);
System.out.println(dalis);
Konsolės rezultatas

3.33

Skaičius 2 nurodo du skaitmenis po kablelio. RoundingMode.HALF_UP reiškia mums įprastą apvalinimą: penketas ir didesnis skaitmuo apvalina aukštyn.

equals() ir compareTo()

BigDecimal a = new BigDecimal("2.0");
BigDecimal b = new BigDecimal("2.00");

System.out.println(a.equals(b));
System.out.println(a.compareTo(b) == 0);
Konsolės rezultatas

false
true

equals() tikrina ir skaitinę reikšmę, ir skalę, todėl 2.0 bei 2.00 jam skiriasi. compareTo() lygina skaitinę vertę, todėl abiejų skaičių vertę laiko vienoda.

Tikslumo kaina

BigDecimal reikšmę sudaro sveikasis skaičius ir skalė – skaitmenų po kablelio kiekis. Pavyzdžiui, 12.50 galima suvokti kaip sveikąją reikšmę 1250 ir skalę 2.

Toks modelis suteikia didelį tikslumą, tačiau objektų kūrimas ir aritmetikos metodai paprastai naudoja daugiau atminties bei veikia lėčiau nei primityvieji double ar long.

  • Rinkis BigDecimal, kai svarbus tikslus dešimtainis rezultatas, ypač pinigams.
  • Rinkis double, kai svarbesnis greitis, o nedidelė paklaida priimtina, pavyzdžiui, daugelyje fizikos skaičiavimų.
  • Galima naudoti long mažiausiems pinigų vienetams, pavyzdžiui, centams, jei mastelis visoje sistemoje aiškiai sutartas.
  • BigInteger skirtas labai dideliems sveikiesiems skaičiams be trupmeninės dalies.