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);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);0.30
- Importuojama klasė
java.math.BigDecimal. - Skaičiai konstruktoriui perduodami kaip tekstas, todėl jų dešimtainė reikšmė išlieka tiksli.
- Sudėčiai naudojamas metodas
add(), o ne operatorius+. - Rezultatas išsaugomas naujame
BigDecimalobjekte.
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ądoubletekstinę išraišką.new BigDecimal(0.1)perima jau egzistuojančią dvejetainiodoublepaklaidą, todėl jo geriau vengti.
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.5014.50
11.00
37.50
| Veiksmas | Metodas |
|---|---|
| Sudėtis | add() |
| Atimtis | subtract() |
| Daugyba | multiply() |
| Dalyba | divide() |
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);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);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);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.

