Utilizarea java.math.MathContext

Recent am încercat să înțeleg folosirea java.math.MathContext , dar nu am reușit să înțeleg corect. Se folosește pentru rotunjirea în java.math.BigDecimal , dacă da, de ce nu este rotundă cifrele zecimale, dar chiar și partea mentesa.

Din documentele API, am aflat că respectă specificațiile specificate în specificațiile ANSI X3.274-1996 și ANSI X3.274-1996 / AM 1-2000 , dar I nu le-au făcut să citească online.

Te rog să-mi spui dacă ai vreo idee despre asta.

0
fr hi bn

5 răspunsuri

Nu este pentru distracție. De fapt, am găsit un exemplu online, care a indicat utilizarea MathContext pentru a răsfoi sumele / numerele stocate în BigDecimal.

De exemplu,

If MathContext is configured to have precision = 2 and rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, is rounded to 0.53

Așa că am crezut că este o tehnică mai nouă și o folosește pentru scopuri de rotunjire. Cu toate acestea, sa transformat în coșmar, deoarece a început să rotunjim chiar o parte a numerelor.

De exemplu,

Number = 1.5294 is rounded to 1.5

Number = 10.5294 is rounded to 10

Number = 101.5294 is rounded to 100

.... si asa mai departe

Deci, acesta nu este comportamentul pe care l-am așteptat pentru rotunjire (ca precizie = 2).

Se pare că are o anumită logică, deoarece de la patter pot să spun că este nevoie de primele două cifre (ca fiind de 2 cifre de număr) și apoi se adaugă 0 până la nr. din cifre devin identice cu suma neincluse (a se vedea exemplul din 101.5294 ...)

0
adăugat
deci vă puteți sugera și pentru soluție?
adăugat autor Sumit Ramteke, sursa

Dacă vă înțeleg corect, suna ca și cum ați aștepta MathContext pentru a controla câte cifre ar trebui păstrate după punctul zecimal. Nu este pentru asta. Specifică câte cifre trebuie păstrate, total . Deci, dacă specificați că doriți 3 cifre semnificative, asta e tot ce veți obține.

De exemplu, aceasta:

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(20)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(10)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(5)));

va produce:

1234567890.123456789
1234567890
1.2346E+9
0
adăugat
Aceasta nu este o întrebare pentru BigDecimal. Cu BigDecimal, ar trebui să specificați numărul de cifre semnificative. Câte cifre după punct zecimal ar trebui să fie determinate la formatarea pentru afișare. Puteți controla acest lucru cu String.format() sau DecimalFormat.format ().
adăugat autor Derek Park, sursa
@Drew Cred că puteți folosi metoda BigDecimal.setScale pentru aceasta. Primul parametru (scală) specifică câte numere doriți să păstrați după punctul zecimal, iar al doilea parametru (rotunjire) specifică comportamentul de rotunjire dorit.
adăugat autor Quazi Irfan, sursa
@Drew Aici este un răspuns care explică acest lucru în mai multe detalii.
adăugat autor Quazi Irfan, sursa
Mulțumesc. Cum aș alege câte cifre să păstrez după zecimală?
adăugat autor Drew, sursa

@jatan

Vă mulțumim pentru răspuns. Are sens. Îmi puteți explica MathContext în contextul metodei rotunde BigDecimal #.

Nu este nimic special în ceea ce privește BigDecimal.round() vs orice altă metodă BigDecimal . În toate cazurile, MathContext specifică numărul de cifre semnificative și tehnica de rotunjire. Practic, există două părți ale fiecărui MathContext . Există o precizie și există și RoundingMode .

Precizia specifică din nou numărul de cifre semnificative. Deci, dacă specificați 123 ca număr și cereți 2 cifre semnificative, veți obține 120 . Ar putea fi mai clară dacă gândiți în termeni de notație științifică.

123 would be 1.23e2 in scientific notation. If you only keep 2 significant digits, then you get 1.2e2, or 120. By reducing the number of significant digits, we reduce the precision with which we can specify a number.

Partea RoundingMode specifică modul în care ar trebui să rezolvăm pierderea de precizie. Pentru a reutiliza exemplul, dacă utilizați 123 ca număr și solicitați 2 cifre semnificative, v-ați redus precizia. Cu RoundingMode din HALF_UP (modul implicit), 123 va deveni 120 . Cu RoundingMode de CEILING , veți primi 130 .

De exemplu:

System.out.println(new BigDecimal("123.4",
                   new MathContext(4,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.CEILING)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(1,RoundingMode.CEILING)));

ieşiri:

123.4
1.2E+2
1.3E+2
2E+2

Puteți vedea că atât precizia, cât și modul de rotunjire afectează ieșirea.

0
adăugat
Există o modalitate de a formata 123.4 folosind 2 cifre semnificative care rezultă într-un șir ca 120 ? Acestea sunt două cifre semnificative (așa cum este 1.2E2 ), deoarece zerourile de tracțiune nu sunt incluse convențional în recuperarea cifrelor semnificative, cu excepția cazului în care există o zecimală finală. Și pentru scopurile mele, dacă numărul care urmează a fi formatat a fost 103.4 , nu-mi pasă că nu puteți spune că există 2 fig smochine în numărul 100 rezultat. Vreau doar o vizualizare mai simplă / mai curată
adăugat autor hepcat72, sursa

Aș adăuga aici câteva exemple. Nu le-am găsit în răspunsurile anterioare, dar le consider util pentru cei care pot induce în eroare cifrele semnificative cu numărul de zecimale . Să presupunem că avem un astfel de context:

MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);

Pentru acest cod:

BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);

este clar că rezultatul dvs. este 1.23E + 3 așa cum spuneau mai sus băieții. Primele cifre semnificative sunt 123 ...

Dar ceea ce în acest caz:

BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);

numărul dvs. nu va fi rotunjit la 3 locuri după virgulă - pentru cineva care nu poate fi intuitivă și merită subliniată. În schimb, acesta va fi rotunjit la primele 3 cifre semnificative , care în acest caz sunt "4 5 4". Deci, codurile de mai sus rezultă în 4.55E-7 și nu în 0.000 după cum se poate aștepta cineva.

Exemple similare:

BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX);
 System.out.println(d3);  // 0.00100

BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX);
 System.out.println(d4);   // 0.200

BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX);
    System.out.println(d5); //4.00E-9

Sper că acest exemplu evident, dar relevant ar fi de ajutor ...

0
adăugat

Pentru a rotunji doar partea fracționată a unui BigDecimal, verificați metoda BigDecimal.setScale (int newScale, int roundingMode) .

De exemplu. pentru a schimba un număr cu trei cifre după punct zecimal la unul cu două cifre și rotunjire în sus:

BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);

Rezultatul este un BigDecimal cu valoarea 1.24 (din cauza regulii de rotunjire)

0
adăugat
Acesta este răspunsul pe care îl doresc oamenii, lucrând cu numere zecimale fixe și menținând un număr fix de zecimale. Nu știu de ce Soarele a bătut "precizia" stilului cu virgulă înăuntru, dar asta este ceea ce este MathContext.
adăugat autor Thomas W, sursa