BigDecimal talouslaskennassa
Käytä BigDecimalia liukulukujen tarkkuusvirheiden välttämiseen raha- ja verolaskennassa.
BigDecimal talouslaskennassa on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
BigDecimal talouslaskennassa
Liukulukutyypit (double, float) eivät binääriesityksen vuoksi pysty esittämään kaikkia desimaaliarvoja täsmällisesti. Käyttäkää rahasummiin ja veroihin BigDecimal-tyyppiä.
Liukulukujen ongelma
Binääriset liukuluvut aiheuttavat pieniä pyöristysvirheitä. Taloussovelluksissa nämä virheet kasaantuvat ja aiheuttavat todellisia ongelmia.
double price = 0.1 + 0.2;
System.out.println(price); // 0.30000000000000004 (WRONG!)
System.out.println(price == 0.3); // false
// Real bug: total never equals expected
double total = 0;
for (int i = 0; i < 10; i++) total += 0.1;
System.out.println(total); // 0.9999999999999999BigDecimal-olion luominen turvallisesti
Luokaa BigDecimal aina String-merkkijonosta, älkää double-arvosta. double-rakentajan käyttäminen perii liukulukujen epätarkkuuden.
import java.math.BigDecimal;
// WRONG: double constructor
BigDecimal wrong = new BigDecimal(0.1);
System.out.println(wrong); // 0.1000000000000000055511...
// CORRECT: String constructor
BigDecimal correct = new BigDecimal("0.1");
System.out.println(correct); // 0.1
// Or use valueOf (also safe)
BigDecimal safe = BigDecimal.valueOf(0.1);
System.out.println(safe); // 0.1Peruslaskutoimitukset BigDecimal-tyypillä
BigDecimal käyttää laskutoimituksiin menetelmäkutsuja: add(), subtract(), multiply() ja divide(). Nämä palauttavat uusia BigDecimal-olioita (tyyppi on muuttumaton).
import java.math.BigDecimal;
BigDecimal price = new BigDecimal("19.99");
BigDecimal tax = new BigDecimal("0.08");
BigDecimal qty = new BigDecimal("3");
BigDecimal subtotal = price.multiply(qty);
BigDecimal taxAmount = subtotal.multiply(tax);
BigDecimal total = subtotal.add(taxAmount);
System.out.println(subtotal); // 59.97
System.out.println(taxAmount); // 4.7976
System.out.println(total); // 64.7676Pyöristystilat
RoundingMode määrittää, miten BigDecimal pyöristetään. Keskeiset tilat:
HALF_UP— tavallinen pyöristys (0.5 pyöristetään ylöspäin)HALF_EVEN— pankkipyöristys (0.5 pyöristetään lähimpään parilliseen lukuun)DOWN— katkaisu kohti nollaaCEILING— pyöristys kohti positiivista ääretöntä
import java.math.*;
BigDecimal val = new BigDecimal("2.565");
System.out.println(val.setScale(2, RoundingMode.HALF_UP)); // 2.57
System.out.println(val.setScale(2, RoundingMode.HALF_EVEN)); // 2.56 (banker's)
System.out.println(val.setScale(2, RoundingMode.DOWN)); // 2.56
System.out.println(val.setScale(2, RoundingMode.CEILING)); // 2.57Jako ja skaala
BigDecimal-tyypillä jaettaessa on määritettävä skaala ja pyöristystila, jotta päättymättömät desimaalit eivät aiheuta ArithmeticException-poikkeusta.
import java.math.*;
BigDecimal revenue = new BigDecimal("1000.00");
BigDecimal months = new BigDecimal("3");
// Without scale → ArithmeticException (non-terminating decimal)
try {
revenue.divide(months);
} catch (ArithmeticException e) {
System.out.println("Need to specify scale!");
}
// Correct: specify scale and rounding
BigDecimal monthly = revenue.divide(months, 2, RoundingMode.HALF_UP);
System.out.println(monthly); // 333.33BigDecimal-arvojen vertaaminen
Vertailkaa arvoja compareTo()-menetelmällä, älkää equals()-menetelmällä. equals() huomioi skaalan – 2.0 ja 2.00 EIVÄT ole equals()-menetelmällä yhtäsuuria, mutta compareTo()-menetelmällä OVAT.
import java.math.BigDecimal;
BigDecimal a = new BigDecimal("2.0");
BigDecimal b = new BigDecimal("2.00");
System.out.println(a.equals(b)); // false (different scale)
System.out.println(a.compareTo(b)); // 0 (same value)
System.out.println(a.compareTo(b) == 0); // true
// For sorting in collections
import java.util.*;
List<BigDecimal> prices = Arrays.asList(
new BigDecimal("3.50"), new BigDecimal("1.00"), new BigDecimal("2.75")
);
Collections.sort(prices);
System.out.println(prices); // [1.00, 2.75, 3.50]MathContext merkitseville numeroille
MathContext määrittää tarkkuuden (merkitsevien numeroiden määrän) ja pyöristystilan. Käyttäkää sitä, kun tarvitsette yhdenmukaisen merkitsevien numeroiden tarkkuuden desimaalien määrän sijaan.
import java.math.*;
MathContext mc = new MathContext(4, RoundingMode.HALF_UP);
BigDecimal a = new BigDecimal("1234567");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b, mc);
System.out.println(result); // 4.115E+5 (4 significant digits)
// DECIMAL32, DECIMAL64, DECIMAL128 are standard MathContexts
BigDecimal precise = new BigDecimal("355").divide(
new BigDecimal("113"), MathContext.DECIMAL64);
System.out.println(precise); // 3.141592920353982...Ostoskoriesimerkki
Esimerkki täydellisestä ostoskorilaskennasta BigDecimal-tyypillä: tuoterivit, vero, alennus ja loppusumma.
import java.math.*;
record LineItem(String name, BigDecimal price, int qty) {
BigDecimal subtotal() {
return price.multiply(new BigDecimal(qty));
}
}
var items = List.of(
new LineItem("Laptop", new BigDecimal("999.00"), 1),
new LineItem("Case", new BigDecimal("29.99"), 2),
new LineItem("Charger", new BigDecimal("49.99"), 1)
);
BigDecimal subtotal = items.stream()
.map(LineItem::subtotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal taxRate = new BigDecimal("0.09");
BigDecimal tax = subtotal.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
BigDecimal total = subtotal.add(tax);
System.out.println("Subtotal: " + subtotal);
System.out.println("Tax: " + tax);
System.out.println("Total: " + total);Stripe: valuutta sentteinä
Stripen kaltaiset maksupalveluntarjoajat tallentavat summat kokonaislukusentteinä, jolloin desimaalien ongelmat vältetään kokonaan. Senttien ja näytettävien summien välinen muunnos on yleinen toimintamalli.
import java.math.*;
// Store as cents (long) for database / API
long amountCents = 999_99L; // $999.99
// Convert to BigDecimal for display
BigDecimal amount = BigDecimal
.valueOf(amountCents)
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
System.out.println("Amount: $" + amount); // Amount: $999.99
// Convert user input back to cents
BigDecimal input = new BigDecimal("49.95");
long cents = input.multiply(new BigDecimal("100"))
.setScale(0, RoundingMode.HALF_UP).longValueExact();
System.out.println("Cents: " + cents); // Cents: 4995Milloin käyttää BigDecimal-tyyppiä ja milloin double-tyyppiä
Valitkaa tarkoitukseen sopiva tyyppi:
- BigDecimal: rahasummat, verot ja laskut, joissa desimaalien täsmällinen esitys on tärkeää
- double: tieteelliset laskelmat, grafiikka ja ML, joissa nopeus on tärkeää ja pienet virheet hyväksyttäviä
- int/long sentteinä: maksujen rajapinnat ja rahasummien tallentaminen tietokantaan
Pikatarkistus
Mitä BigDecimal-vertailumenetelmää tulisi käyttää tarkistettaessa, ovatko kaksi BigDecimal-arvoa numeerisesti yhtäsuuria skaalasta riippumatta?
Kertaus: BigDecimal talouslaskennassa
Keskeiset opit:
- double/float aiheuttavat pyöristysvirheitä – älkää koskaan käyttäkö niitä rahasummiin
- Luokaa BigDecimal String-merkkijonosta tai BigDecimal.valueOf()-menetelmällä, älkää double-arvosta
- Käyttäkää laskutoimituksiin add(), subtract(), multiply() ja divide()
- Määrittäkää jaettaessa aina skaala ja RoundingMode
- Käyttäkää yhtäsuuruustarkistuksiin compareTo()-menetelmää, älkää equals()-menetelmää
- Harkitkaa rahasummien tallentamista kokonaislukusentteinä tietokanta- ja API-käytössä
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”BigDecimal talouslaskennassa” ilmainen?
Kyllä – oppitunnin ”BigDecimal talouslaskennassa” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”BigDecimal talouslaskennassa”?
Käytä BigDecimalia liukulukujen tarkkuusvirheiden välttämiseen raha- ja verolaskennassa. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”BigDecimal talouslaskennassa”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Math-luokan perusteet
- Kokonaislukulaskenta ja ylivuoto
- BigDecimal talouslaskennassa
- NumberFormat ja printf