Jinsi ya Kukata Desimali katika Java (kubadilisha int, Math.floor, BigDecimal setScale)

目次

1. “Truncating Decimals” Inamaanisha Nini katika Java?

Wakati watu wanasema “truncate decimals” katika Java, kwa kawaida wanamaanisha ama kuondoa sehemu ya sehemu ya desimali ili kupata integer au kutoa tarakimu baada ya sehemu ya n‑th ya desimali.
Katika msimbo wa ulimwengu halisi, hata hivyo, “truncate” inaweza kumaanisha zaidi ya kitu kimoja, kwa hivyo hebu tufafanue hitimisho kwanza.

1.1 Je, “truncate” inamaanisha floor? Au cast? (Maneno)

Kuna aina mbili kuu za “truncation.”

  • (A) Truncation kuelekea 0 (truncate) Inafuta sehemu ya desimali, lakini kwa nambari hasi inasogea “karibu zaidi na sifuri.” Mifano: 3.9 → 3 , -3.9 → -3 → Katika Java, (int) casting ina tabia hii
  • (B) Truncation kuelekea −∞ (floor) Inashuka (kuelekea thamani ndogo) kwenye mstari wa nambari Mifano: 3.9 → 3 , -3.9 → -4 → Katika Java, Math.floor() ina tabia hii

Wanaoanza mara nyingi wanachanganyikiwa kwa sababu kwa nambari chanya, (A) na (B) hutoa matokeo sawa.
Lakini mara unaposhughulikia nambari hasi, matokeo yanatofautiana.

1.2 Makala Hii Inakusaidia Kufanya Nini (Njia ya Haraka kwa Kesi ya Matumizi)

Watu wanaotafuta “java truncate decimals” kwa kawaida wanataka mojawapo ya yafuatayo.

  • Kurekebisha tu kuwa integer (mfano, 3.14 → 3) → Ku-cast kwa (int) ni ya haraka zaidi. Lakini kuwa mwangalifu na nambari hasi.
  • Truncate kwenye sehemu 2 za desimali (mfano, 1.239 → 1.23)Math.floor(x * 100) / 100 inaweza kufanya kazi → Lakini ikiwa usahihi ni muhimu, BigDecimal ni salama zaidi
  • Fedha/malipo/viwango ambako makosa hayakubaliwa → Tumia BigDecimal + setScale + RoundingMode

Ukichagua njia isiyo sahihi, mara nyingi “inaonekana kufanya kazi” lakini itavunjika baadaye.
Haswa, mahesabu yanayotokana na double yanaweza kuleta makosa ya usahihi, hivyo kwa mantiki ya fedha ni salama kuanzisha na BigDecimal tangu mwanzo.

1.3 Makosa ya Kawaida (Rekebisha Haya Kwanza)

Makosa matatu ya kawaida ni:

  • Kudhani (int) daima inamaanisha floor → Kwa kweli inarudia kuelekea sifuri, hivyo nambari hasi zinatofautiana.
  • Kutumia Math.floor kwa kukata desimali, lakini kupata tofauti ndogo → Mara nyingi husababishwa na usahihi wa double (hutegemea thamani/mazingira).
  • Kutumia uformat (DecimalFormat, nk) kana kwamba hubadilisha thamani iliyohesabiwa → Muonekano unaweza kubadilika wakati thamani ya ndani inabaki ile ile.

Kwanza thibitisha njia fupi zaidi: “Ukihitaji integer tu, fanya cast.” Kisha elewa “mkoba wa nambari hasi.”

Katika sehemu inayofuata, tutaelezea truncation kupitia (int) casting kwa mifano halisi.

2. Ikiwa Unataka int Tu, Casting Inafanya Kazi (Lakini Kuna Kikwazo)

Ukihitaji tu kuondoa sehemu ya desimali na kupata integer (int), njia ya haraka zaidi katika Java ni casting (ubadilishaji wa aina).
Lakini casting si “truncation ya kihesabu (floor).” Ni kukaribia sifuri (truncate), jambo linaloweza kuwa na athari kubwa.

2.1 Misingi: Truncate Sehemu ya Desimali kwa (int)

Unapobadilisha double au float kuwa int, sehemu ya desimali inatupwa.

double x = 3.99;
int a = (int) x;
System.out.println(a); // 3

Hii ndiyo jibu rahisi zaidi kwa nia ya kawaida “Nataka kukata desimali.”

Hatua ni hizi:

  • Thibitisha thamani ni double / float
  • Ongeza (int) ili ku-cast kuwa int
  • Hakiki matokeo—pamoja na nambari hasi ikiwa zinaweza kutokea

2.2 Muhimu: Casting Inakaribia Sifuri (Nambari Hasi Zinatofautiana)

Huu ndio mkoba wa #1 kwa wanaoanza.
Casting haifanyi “kutoa hadi thamani ndogo zaidi” kila wakati.

System.out.println((int) 3.9);   // 3
System.out.println((int) -3.9);  // -3

-3.9 ikigeuka kuwa -3 (siyo -4) hutokea kwa sababu casting inabadilisha katika mwelekeo karibu zaidi na sifuri.

  • 3.9 → 3 (karibu sifuri)
  • -3.9 → -3 (karibu sifuri)

Ukihitaji “truncation ya kihesabu (floor),” unahitaji Math.floor(), si casting.
Ukikosa hii, unaweza kupata hitilafu katika vitu kama hesabu za P&L, hesabu za ada, au hesabu za kuratibu, ambapo pande hasi pekee ndizo zilizo sahihi.

2.3 Makosa ya Kawaida: Kufikiri Kuhesabu / Kuvunja kwa Nambari Hasi

Kukata (casting) si kukokotoa kwa karibu zaidi.
Ikiwa unafikiri “0.9 inakuwa 1,” utakuwa na kosa.

System.out.println((int) 0.9);  // 0
System.out.println((int) 1.9);  // 1

Pia, kwa nambari hasi inaweza kuhisi kama thamani “imeongezeka” au “imepungua” bila kutarajia.

  • -3.9 → -3 husonga katika muelekeo mkubwa kwenye mstari wa nambari
  • Kama ulitarajia -4, hii ni hitilafu halisi

Suluhisho ni rahisi:

  • Kama unashughulikia tu thamani chanya → kukata (casting) ni sawa
  • Kama thamani hasi zinaweza kuonekana → fikiria Math.floor()
  • Kama unahitaji usahihi mkali (pesa, nk.) → fikiria BigDecimal

Katika sehemu ijayo, tutaelezea Math.floor() / Math.ceil(), ambayo hukuruhusu kukata kwa njia ya kihesabu thabiti hata kwa nambari hasi.

3. Tumia Math.floor / Math.ceil kwa Kukata Desimali kwa Usahihi

Kama unataka kukata desimali kwa usahihi wa kihesabu, njia ya msingi ni kutumia Math.floor() badala ya kukata. Haswa wakati nambari hasi zinaweza kuonekana, kuchagua tu Math.floor() hupunguza hitilafu kwa kiasi kikubwa.

3.1 Kukata kwa Math.floor() (Kazi ya Sakafu)

Math.floor() huitwa kazi ya sakafu na hukokotoa thamani chini (kuelekea thamani ndogo) kwenye mstari wa nambari.

System.out.println(Math.floor(3.9));   // 3.0
System.out.println(Math.floor(-3.9));  // -4.0

Mambo Muhimu:

  • 3.9 → 3.0 (husonga chini)
  • -3.9 → -4.0 (husonga zaidi chini)

Faida kubwa ni kwamba kukata hakifanyi tabia isiyotarajiwa kwa nambari hasi.

Kukosea kunakojulikana ni kwamba Math.floor() hurudisha double. Ikiwa unahitaji integer, lazima uibadilishe baadaye.

3.2 Math.ceil() Hukokotoa Juu — Usichanganye

Math.ceil() ni kinyume cha Math.floor() na hukokotoa juu (kuelekea thamani kubwa) kwenye mstari wa nambari.

System.out.println(Math.ceil(3.1));   // 4.0
System.out.println(Math.ceil(-3.1));  // -3.0

Kukosea kunakojulikana ni:

  • Kufikiri “ondoa desimali” inamaanisha ceil → Kwa kweli, ceil hukokotoa juu, ambayo mara nyingi ni kinyume cha kile unachotaka.

Kama ulitafuta “kukata desimali,” floor kawaida ni chaguo sahihi.

3.3 Ubadilishaji wa Aina Wakati Unabadilisha kuwa long / int

Kama unataka kubadilisha matokeo ya Math.floor() kuwa int au long, unahitaji kukata (cast) hiyo.

double x = -3.9;

int a = (int) Math.floor(x);
System.out.println(a); // -4

Mambo ya kuangalia:

  • Matokeo ya Math.floor() ni double
  • Kukata hadi int huondoa sehemu ya desimali (hakuna kutokilingana katika hatua hii)
  • Kama thamani ni kubwa sana, inaweza isijumui kwenye int

Kwa usalama, unaweza kuchagua long kwanza.

double x = 12345678901.9;

long b = (long) Math.floor(x);
System.out.println(b); // 12345678901

Makosa ya kawaida yanajumuisha:

  • Kusahau kukata na kuacha thamani kama double
  • Kutofahamu tofauti kati ya floor na casting, kusababisha hitilafu kwa hasi
  • Kuzidi ukubwa (overflow) wakati thamani inazidi upeo wa int

Kwa kifupi, ikiwa nambari hasi zinaweza kuhusika, ni salama zaidi kubuni kwa kutumia Math.floor() tangu mwanzo.

Katika sehemu ijayo, tutaelezea jinsi ya kukata katika sehemu ya n-th desimali (kwa mfano, kuweka desimali mbili) kwa mifano halisi.

4. Jinsi ya Kukata katika Sehemu ya n-th Desimali (Kawaida katika Maonyesho & Mahesabu)

Katika matumizi halisi, ni kawaida sana kutaka kushikilia hadi sehemu fulani ya desimali na kuondoa mengine, si tu kuondoa desimali zote. Mifano ni viwango vya kodi, viwango vya ubadilishaji, bei za kitengo, na asilimia.

Hapa tunapanga njia za vitendo za kukata katika sehemu ya n-th desimali. Unapotumia double, matatizo ya usahihi yanaweza kutokea, hivyo tutashughulikia vizingiti pia.

4.1 Muundo wa Msingi: Zidisha kwa 10^n, floor, kisha gawanya

  1. Amua idadi ya sehemu za desimali n
  2. Zidisha kwa 10^n
  3. Tumia Math.floor()
  4. Gawanya kwa 10^n ili kurejesha kiwango

Kwa kukata hadi sehemu 2 za desimali (mfano, 1.239 → 1.23):

double x = 1.239;
double y = Math.floor(x * 100) / 100;
System.out.println(y); // 1.23

Kwa kukata hadi sehemu 3 za desimali (mfano, 1.2399 → 1.239):

double x = 1.2399;
double y = Math.floor(x * 1000) / 1000;
System.out.println(y); // 1.239

Faida za mbinu hii:

  • Code fupi na rahisi
  • Inatumia Math.floor() , kwa hivyo tabia na nambari hasi ni sawa
  • Hakuna maktaba za ziada zinazohitajika

Hata hivyo, kwa sababu hii inategemea double, haiendani kwa hesabu kali kama pesa.

4.2 Tishio: Matokeo Yasiyotarajiwa Kutokana na Usahihi wa double

double ya Java ni aina ya nambari-tupu na haiwezi kuwakilisha thamani kama 0.1 au 0.01 kwa usahihi daima.
Kutokana na hivyo, unaweza kuona tofauti zinazoonekana “zisizofaa” (kutegemea thamani na mazingira).

  • Unatarajia 1.29 , lakini inaonekana kama 1.28
  • Unashughulikia 0.3 , lakini ndani yake ni 0.299999999...

Kwa mfano, code ifuatayo inaonekana sahihi kimantiki:

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

Lakini ndani, x * 100 inaweza kuwakilishwa kama 128.999999999....
Ikiwa floor inarudisha 128, matokeo yanakuwa 1.28.
Hii si hitilafu katika Java, bali sifa ya hesabu ya nambari-tupu.

Sehemu ngumu ni kwamba hii hutokea mara chache tu, ambayo inafanya iwe ngumu kuigusa wakati wa majaribio.

4.3 Kukata Kwa Usalama na BigDecimal (Inapendekezwa)

Ikiwa unataka kukata katika sehemu ya n-th ya desimali kwa kuaminika, kutumia BigDecimal ni chaguo salama zaidi.
BigDecimal inashughulikia nambari za msingi-10 kwa usahihi na hutumiwa sana kwa hesabu za pesa.

Mfumo msingi ni:

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // truncate at 2 decimal places
System.out.println(y); // 1.23

Mambo muhimu:

  • setScale(2, ...) inahifadhi sehemu mbili za desimali
  • RoundingMode.DOWN inabainisha kukata kuelekea sifuri

Kumbuka kuwa DOWN ya BigDecimal si sawa na Math.floor().
Na nambari hasi, tabia hutofautiana, kwa hivyo unaweza pia kuhitaji kufikiria FLOOR (imeelezwa baadaye).

Makosa ya kawaida ni pamoja na:

  • Kuunda BigDecimal kutoka double (kuanzisha makosa ya usahihi)
  • Kusahau kuita setScale
  • Kutumia hali ya kurudia vibaya na kurudia nusu juu kwa bahati mbaya

Kwa muhtasari, Math.floor inaweza kuwa ya kutosha kwa madhumuni ya kuonyesha pekee, lakini kwa hesabu muhimu, BigDecimal ni chaguo salama zaidi.

Katika sehemu ijayo, tutachunguza zaidi kukata kwa BigDecimal, pamoja na njia sahihi ya kuunda mifano kwa code ya ulimwengu halisi.

5. Kukata na BigDecimal (Salama Zaidi kwa Fedha, Malipo, na Viwango)

Ikiwa unataka kukata desimali kwa usahihi wa juu zaidi, BigDecimal inapaswa kuwa chaguo lako la kwanza katika Java.
double ni haraka lakini ina hatari ya makosa ya usahihi, ambayo mara nyingi husababisha matatizo baadaye katika pesa, malipo, ada, au hesabu za viwango.
BigDecimal inashughulikia nambari za desimali kwa njia inayokaribia matarajio ya binadamu, kwa hivyo hutumiwa sana katika code ya biashara.

5.1 Misingi ya BigDecimal: Kuunda kutoka double Ni Hatari (Muhimu Zaidi)

Kosa la kawaida sana na BigDecimal ni jinsi inavyoundwa.
Ikiwa utapitisha double moja kwa moja, kosa la usahihi la ndani linaweza kuhifadhiwa.

import java.math.BigDecimal;

BigDecimal a = new BigDecimal(0.1);
System.out.println(a); // May become something like 0.10000000000000000555...

Kukata au kuhesabu na thamani hii mara nyingi husababisha tofauti “zisizofahamika”.

Njia salama za kuunda BigDecimal ni:

(A) Unda kutoka String (wazi zaidi na salama)

BigDecimal a = new BigDecimal("0.1");

(B) Tumia BigDecimal.valueOf(double) (mara nyingi inapendekezwa)

BigDecimal a = BigDecimal.valueOf(0.1);

Kwa wanaoanza, kanuni salama zaidi ni: ukikua na shaka, unda BigDecimal kutoka kwa String.

5.2 Kata kwenye sehemu n za desimali kwa RoundingMode.DOWN

Ili kukata kwenye sehemu ya desimali ya n, tumia setScale.

  • setScale(2, ...) → hifadhi sehemu mbili za desimali
  • RoundingMode.DOWN → kata kuelekea sifuri
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    
    BigDecimal x = new BigDecimal("123.4567");
    BigDecimal y = x.setScale(2, RoundingMode.DOWN);
    
    System.out.println(y); // 123.45
    

Kama unataka kuondoa desimali zote na kupata thamani kama nambari kamili, njia ileile inatumika.

BigDecimal x = new BigDecimal("123.999");
BigDecimal y = x.setScale(0, RoundingMode.DOWN);

System.out.println(y); // 123

Kipengele muhimu: setScale hubadilisha thamani yenyewe, si tu jinsi inavyoonyeshwa.
Hii ni operesheni ya hesabu, si uumbaji wa muundo.

5.3 Kata kuelekea Sifuri vs Mwelekeo wa Floor (Tofauti Muhimu)

BigDecimal inatoa njia nyingi za kukokotoa, na kuna mbili zinazofanana na “ukataji,” ambazo zinaweza kuchanganya.

  • RoundingMode.DOWN : kata kuelekea sifuri
    • 3.9 → 3
    • -3.9 → -3
  • RoundingMode.FLOOR : kata kuelekea −∞ (sakafu ya kihesabu)
    • 3.9 → 3
    • -3.9 → -4

Kama unataka thamani daima ziende upande mdogo kwenye mstari wa nambari, FLOOR ndiyo chaguo sahihi.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x1 = new BigDecimal("-3.9");
System.out.println(x1.setScale(0, RoundingMode.DOWN));  // -3
System.out.println(x1.setScale(0, RoundingMode.FLOOR)); // -4

Kile kilicho “sahihi” kinategemea kabisa matumizi yako.

  • Kuondoa tarakimu tu (ukataji) → DOWN
  • Ukataji wa kihesabu (sakafu) → FLOOR

Kama tofauti hii haijulikani, thamani hasi zinaweza kusababisha hitilafu kubwa za maelezo.

5.4 Makosa ya Kawaida ya BigDecimal

Hapa kuna makosa ya kawaida wakati wa kukata kwa BigDecimal:

  • Kujenga BigDecimal kutoka double na kuleta makosa ya usahihi → Epuka new BigDecimal(0.1) ; tumia String au valueOf
  • Kutumia skeli isiyo sahihi → Kwa mfano, kutumia 0 badala ya sehemu 2 za desimali
  • Kuchanganya njia za kukokotoa → Kuchanganya DOWN na FLOOR, kusababisha matatizo na nambari hasi
  • Kubadilisha thamani unapokusudia tu kuunda muundosetScale hubadilisha thamani; tenganisha hesabu na onyesho

Kwa kifupi, kwa fedha, bili, au viwango—ambapo tofauti ya senti moja tu ina maana—
tumia BigDecimal na rekebisha njia ya uundaji pamoja na njia ya kukokotoa.

Katika sehemu ijayo, tutaelezea jinsi ya kuepuka kuchanganya muundo wa onyesho na ukataji wa hesabu.

6. DecimalFormat / String.format Ni kwa Onyesho Pekee (Usitumie kwa Hesabu)

Unapokata desimali, ni muhimu kutofautisha kama unataka kukata thamani iliyohesabiwa au kuunda muundo wa onyesho tu.
Kuchanganya hizi mbili kunasababisha hali ambapo skrini inaonekana sahihi lakini thamani ya ndani si sahihi, na kusababisha hitilafu baadaye.

Mafunzo muhimu: DecimalFormat na String.format ni kwa onyesho pekee.
Kama unahitaji kukata thamani halisi, tumia BigDecimal au Math.floor().

6.1 Kuunda Sehemu za Desimali kwa DecimalFormat (Kukata Inawezekana)

DecimalFormat ni darasa la kubadilisha nambari kuwa mistari iliyopangwa.
Kwa mfano, mara nyingi hutumika unapohitaji kuonyesha sehemu mbili za desimali.

import java.text.DecimalFormat;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(x)); // May become 1.24 (rounded)

Kile muhimu ni kwamba thamani inayorudishwa na format() ni String,
na thamani ya nambari ya x yenyewe haibadiliki.

Unaweza pia kubainisha njia ya kukokotoa.
Ili kukata onyesho, fanya yafuatayo:

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // 1.23

However, this only changes the displayed string; the value of x remains unchanged.

6.2 Caveats When Using String.format

String.format also lets you control numeric output formatting.

double x = 1.239;
System.out.println(String.format("%.2f", x)); // Often rounds to 1.24

In many cases, String.format("%.2f", x) performs round half up behavior.
It’s usually unsuitable if you specifically want truncation.

A very common beginner mistake is converting a formatted string back into a number and using it in calculations.

double x = 1.239;
String s = String.format("%.2f", x); // "1.24"
double y = Double.parseDouble(s);    // 1.24

// At this point, calculations use a rounded value, not a truncated one

This mixes display concerns into calculation logic, making future changes harder.

6.3 Key Pitfall: Correct Display Does Not Mean Correct Values

The most dangerous assumption is “it looks correct on the screen, so it must be fine.”

  • DecimalFormat / String.format change how values look
  • Math.floor / BigDecimal.setScale change the actual value

If you confuse these, you may run into problems like:

  • The UI shows “$1.23” but internal calculations still sum “$1.239”
  • Rounding happens at the wrong stage, causing billing totals to differ
  • Display rounding leaks into calculations, causing audit discrepancies

A simple rule of thumb:

  • Only formatting for display → DecimalFormat (or UI formatting)
  • Truncating as part of calculation → BigDecimal / Math.floor

In the next section, we’ll provide a quick reference table so you can instantly choose the right approach by use case.

7. Best Practices by Use Case (Quick Reference)

“Java decimal truncation” is confusing because there are multiple valid approaches.
Here, we fix the decision by mapping use case → best solution, so you can choose quickly.

7.1 Convert to int (Positive Numbers Only) → Casting Is Enough

If you just want to remove decimals and convert to int, and negative numbers will never appear, casting is the fastest option.

double x = 12.99;
int y = (int) x;
System.out.println(y); // 12

Things to remember:

  • Casting rounds toward zero
  • With positive values, it looks the same as truncation
  • If negatives may appear, don’t lock in this approach

7.2 Truncate Including Negative Numbers → Math.floor

If you want mathematical truncation (floor), Math.floor() is the correct choice.
It’s safer than casting when negative numbers may occur.

double x = -3.9;
int y = (int) Math.floor(x);
System.out.println(y); // -4

Common notes:

  • Math.floor() returns a double
  • Cast to int or long if needed
  • Watch out for int overflow with large values

7.3 Truncate at the n-th Decimal Place (Strict) → BigDecimal + setScale

If you want to truncate at a specific decimal place without precision errors, BigDecimal is the safest option.

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN);

System.out.println(y); // 1.23

This approach is ideal for:

  • Money (JPY, USD, etc.)
  • Billing and tax calculations
  • Rate calculations where errors are unacceptable
  • Batch jobs requiring deterministic results

Common pitfalls:

  • Do not create BigDecimal from double (avoid new BigDecimal(0.1) )
  • Understand the difference between DOWN and FLOOR (negative numbers)

7.4 Format for Display Only → DecimalFormat (Never for Calculation)

If you only want to format numbers for display (e.g., two decimals), DecimalFormat is convenient.
However, it does not change the underlying numeric value, so never use it for calculations.

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Maelezo:

  • Thamani ya kurudi ni String
  • Kuchanganya mantiki ya kuonyesha katika hesabu husababisha makosa

Kwa sentensi moja, hitimisho ni:

  • Haraka & rahisi → Kutupia
  • Sahihi na saliti → Math.floor
  • Usahihi wa kwanza (dunia halisi) → BigDecimal
  • Onyesha pekee → DecimalFormat

Kisha, tutafupisha makosa ya kawaida na jinsi ya kuyiepuka.

8. Makosa ya Kawaida na Onyo Muhimu

Kukatwa kwa desimali mara nyingi “inaonekana kufanya kazi,” hivyo inafanya iwe rahisi kwa wanaoanza kukosa makosa madogo.
Hapa kuna makosa ya dunia halisi na jinsi ya kuyiepuka.

8.1 Kuelewa vibaya Maana ya “Kukatwa” (Kuelekea 0 dhidi ya Floor)

Kosa la kawaida zaidi ni kudhani kukatwa daima inamaanish “nenda ndogo.”
Katika Java, maana inategemea njia.

  • Kutupia (int) : kuelekea sifuri

    • 3.9 → 3
    • -3.9 → -3
    • Math.floor() : kuelekea −∞

    • 3.9 → 3
    • -3.9 → -4

Ikiwa thamani hasi zinawezekana na unatumia kutupia, upande wa hasi pekee utakuwa mbaya.
Hii mara nyingi haijulikani ikiwa vipimo vinatumia thamani chanya pekee.

Hatua za kujikinga:

  • Ikiwa saliti zinaweza kuonekana, zingatia Math.floor() kutoka mwanzo
  • Na BigDecimal, usichanganye RoundingMode.DOWN na FLOOR

8.2 Matokeo Yasiyotarajiwa Kutokana na Usahihi wa double

Unapotekeleza kukatwa kwa Math.floor(x * 100) / 100, unaweza kuona kutofautiana hata kama mantiki inaonekana sahihi.
Sababu ni uwakilishi wa ndani wa double.

double x = 1.29;
double y = Math.floor(x * 100) / 100;
System.out.println(y);

Kutegemea thamani, x * 100 inaweza kuwa 128.999999999..., na kusababisha 1.28.
Kwa sababu hii haifanyiki kila wakati, mara nyingi hugunduliwa katika uzalishaji.

Hatua za kujikinga:

  • Tumia BigDecimal kwa pesa na malipo
  • Ikiwa unatumia double, punguza matumizi kwa kesi ambapo makosa madogo yanakubalika

8.3 Kutumia double kwa Hesabu za Pesa

Kutumia double kwa pesa mara nyingi husababisha:

  • Jumla zisizolingana baada ya kukatwa
  • Makosa madogo ya kurudia yanakusanyika
  • Kutofautiana kati ya iliyoonyeshwa na thamani za ndani

Hatua za kujikinga:

  • Tumia BigDecimal kwa thamani za fedha
  • Rekebisha njia ya kuunda (String au valueOf )
  • Andika sheria za kurudia wazi

8.4 Kutumia Uundaji wa Onyesho kwa Hesabu

Kurekebisha na DecimalFormat au String.format na kisha kuchanganua kurudi kwa nambari ni hatari.

double x = 1.239;
String s = String.format("%.2f", x); // display formatting
double y = Double.parseDouble(s);    // used in calculation (dangerous)

Hii husababisha:

  • Kurudia kwa onyesho kuingia katika hesabu
  • Mabadiliko ya maelezo kuathiri mantiki
  • Kupoteza kujitenga kati ya onyesho na hesabu

Hatua za kujikinga:

  • Maliza hesabu na BigDecimal au Math.floor()
  • Rekebisha tu katika hatua ya mwisho ya onyesho
  • Weka hesabu na uwasilishaji tofauti

9. Muhtasari: Hitimisho za Nakili-Nakili

Kuna njia nyingi za kukatwa desimali katika Java, lakini njia ya haraka zaidi ni chagua kwa kesi ya matumizi.
Hapa kuna hitimisho tayari-kutumia.

9.1 Ikiwa Huwa Hakuna Uhakika, Tumia Hizi

Kesi 1: Badilisha kuwa int (Nambari Chanya Pekee)

double x = 12.99;
int y = (int) x;  // 12

Muhimu: Na nambari hasi, -3.9 → -3, hivyo hii si floor ya hisabati.

Kesi 2: Kukatwa kwa Hisabati Pamoja na Saliti

double x = -3.9;
int y = (int) Math.floor(x); // -4

Wazo: Math.floor() hukata kuelekea −∞.

Kesi 3: Kukatwa katika Sehemu n za Desimali (double, rahisi)

*Tumia tu wakati makosa madogo ya usahihi yanakubalika.

double x = 1.239;
double y = Math.floor(x * 100) / 100; // 1.23

Onyo: Masuala ya usahihi wa double yanaweza kutokea. Kwa usahihi mkali, tumia BigDecimal.

Kesi 4: Kata kwa Uaminifu kwenye N Nafasi za Desimali (Inashauriwa)

import java.math.BigDecimal;
import java.math.RoundingMode;

BigDecimal x = new BigDecimal("1.239");
BigDecimal y = x.setScale(2, RoundingMode.DOWN); // 1.23

Vidokezo muhimu:

  • Usiunde BigDecimal kutoka double
  • Tumia hii kwa pesa, bili, na viwango

Kesi 5: Onyesha Tu (Kamwe kwa Mahesabu)

import java.text.DecimalFormat;
import java.math.RoundingMode;

double x = 1.239;

DecimalFormat df = new DecimalFormat("0.00");
df.setRoundingMode(RoundingMode.DOWN);

System.out.println(df.format(x)); // "1.23"

Kipengele: Hii inazalisha String; thamani ya nambari haibadiliki.

FAQ

J1. Ni njia rahisi zaidi ya kukata desimali katika Java?

Jibu: Ikiwa unahitaji nambari kamili tu, kutengeneza kwa (int) ni haraka zaidi. Ikiwa nambari hasi zinaweza kuonekana, fikiria Math.floor().

J2. Kwa nini (int) hutoa matokeo yasiyotabirika kwa nambari hasi?

Jibu: Kutengeneza kunakaribia sifuri. Kwa mfano, -3.9 → -3. Kwa kukata kihesabu, tumia Math.floor().

J3. Ninawezaje kukata hadi sehemu mbili za desimali (mfano, 1.239 → 1.23)?

Jibu: Kwa njia rahisi, tumia Math.floor(x * 100) / 100. Kwa usahihi mkali, tumia BigDecimal.setScale(2, RoundingMode.DOWN).

J4. Kwa nini Math.floor(x * 100) / 100 wakati mwingine hutoa thamani zisizo sahihi?

Jibu: Hii ni kutokana na makosa ya usahihi wa double. Kwa pesa au bili, badilisha kwa BigDecimal.

J5. Ni njia sahihi ya kukata kwa kutumia BigDecimal?

Jibu: Unda BigDecimal kutoka String au valueOf, kisha tumia setScale(n, RoundingMode.DOWN). Epuka new BigDecimal(double).

J6. Ni tofauti gani kati ya RoundingMode.DOWN na FLOOR?

Jibu: Zinatofautiana kwa nambari hasi. DOWN inakata kuelekea sifuri; FLOOR inakata kuelekea −∞. Chagua kulingana na unataka kukata au sakafu ya kihesabu.

J7. Je, naweza kukata desimali kwa DecimalFormat?

Jibu: Unaweza kukata onyesho kwa kuweka hali ya kukokota, lakini ni kwa ajili ya onyesho tu. Thamani ya ndani haibadiliki.

J8. Ni lini kukatwa kunapaswa kutumika katika mahesabu?

Jibu: Inategemea maelezo. Amua kama kukata kwa kila hatua au mwishoni, andika kanuni wazi, na utekeleze kwa uthabiti—bora kutumia BigDecimal.