|
|
Postat pe 07.04.2015 14:53:05
|
|
|

Clasele de operare pentru numere mari sunt oferite în java, și anume clasa java.math.BinInteger și clasa java.math.BigDecimal. Aceste două clase sunt folosite pentru calcul de înaltă precizie, clasa BigInteger fiind clasa de procesare pentru numerele întregi mari, iar clasa BigDecimal fiind clasa de procesare pentru numere mari și mici. Mai jos prezentăm clasa BigDecimal: Implementarea BigDecimal profită de BigInteger, cu excepția faptului că BigDecimal adaugă conceptul de zecimale. Datele generale float și de tip dublu pot fi folosite doar pentru calcule științifice sau inginerești, deoarece în calculul comercial acuratețea numerică necesară este relativ ridicată, astfel că se folosește clasa java.math.BigDecimal, care suportă orice precizie a punctelor fixe și poate fi folosită pentru a calcula cu precizie valorile monedei. Mai jos vom prezenta pe scurt utilizarea sa cu exemple
java.math.BigDecimal
Astăzi, am scris un program despre conversia binară și zecimală cu referire la manual, iar algoritmul programului nu este dificil, dar după ce am scris, am descoperit că, indiferent dacă este 2 la 10 sau 10 la 2, nu este o conversie bună pentru numere mai mari de 2,1 miliarde, adică mai mari decât intervalul întregi. va deveni 0. Cărțile de referință au constatat că folosirea BigInteger rezolvă această problemă. Așa că am căutat despre JDK, apoi l-am testat de mai multe ori și în cele din urmă l-am scris cu succes! Experiența de utilizare este următoarea:
1. BigInteger aparține java.math.BigInteger, deci importă această clasă înainte de fiecare utilizare. Ocazional, uitam să import la început, așa că promptul nu poate fi găsit în promptul constant.
2. Există multe metode de construcție, dar acum sunt folosite ocazional: BigInteger (String val) Convertiți reprezentarea șirului zecimal de la BigInteger în BigInteger. BigInteger (String val, int radix) Convertește reprezentarea șirului BigInteger pentru cardinalitatea specificată în BigInteger. Pentru a converti 2 de tip int în tip BigEnterer, scrie BigInteger two=new BigInteger("2"); Notă 2: ghilimelele duble nu pot fi omise
3. Clasa BigInteger simulează toate operațiile matematice de tip int, cum ar fi add()=="+", divide()=="-", etc., dar rețineți că conținutul său nu poate fi folosit direct pentru operații matematice atunci când se efectuează operații matematice și trebuie să utilizeze metodele sale interne. Iar operandul său trebuie să fie de tip BigInteger. De exemplu: two.add(2) este o operație incorectă deoarece 2 nu devine un tip BigNumber.
4. Când doriți să generați rezultatele calculului, ar trebui să folosiți metoda .toString pentru a le converti într-un șir zecimal, așa cum este detaliat după cum urmează: String toString() Returnează reprezentarea șirului zecimal al acestui BigInteger. Metoda de ieșire: System.out.print(two.toString());
5. Explică cele trei funcții folosite. BigInteger remainder(BigInteger val) Returnează un BigInteger cu valoarea (acest % val). BigInteger negate() BigInteger returnează o valoare a (-this). int compareTo(BigInteger val) Compară acest BigInteger cu BigInteger specificat. restul a fost folosit pentru a găsi restul. Negarea transformă operandul în opus. Comparația este explicată în detaliu după cum urmează: compareTo
public int compareTo(BigInteger val)
Compară acest BigInteger cu BigInteger specificat. Această metodă este preferată pentru fiecare dintre cei șase operatori de comparație booleeni (<, ==, >, >=, !=, <=). Afirmația sugerată pentru a efectua aceste comparații este: (x.compareTo(y) <op> 0), unde <op> este unul dintre cei șase operatori de comparație.
Specificator: interfețe<BigInteger> Comparabil
Parametri: val - MareÎntregul care compară acest BigInteger cu acesta. Spate:
Titlu: Implementarea calculelor precise ale numerelor în virgulă mobilă în Java AYellow (Original) Modificare Cuvinte-cheie Java calcul precis al numărului în virgulă mobilă
Întrebare pusă: Ce am vedea dacă am compila și rula următorul program? clasa publică Test{ public static void main(String args[]){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } };
Ai citit bine! Rezultatul este, într-adevăr 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Tipurile simple float și double în Java nu pot fi operate. Această problemă nu se găsește doar în Java, ci și în multe alte limbaje de programare. În majoritatea cazurilor, calculele sunt corecte, dar poți încerca de câteva ori (poți face o buclă) să încerci erori ca cea de mai sus. Acum înțeleg în sfârșit de ce există un cod BCD. Această problemă este destul de serioasă, dacă ai 9,999999999999999999 yuani, calculatorul tău nu va crede că poți cumpăra 10 yuani de bunuri. Unele limbaje de programare oferă tipuri specializate de monedă pentru a gestiona această situație, dar Java nu. Acum să vedem cum să rezolvăm asta.
Rotunjire Prima noastră reacție este să facem rotunjire. Metoda rotundă din clasa de Matematică nu poate fi setată să păstreze câteva zecimale, putem face asta doar (păstrăm două locuri): Dublă rundă publică (valoare dublă){ returnează Math.round(value*100)/100.0; }
Din păcate, codul de mai sus nu funcționează, iar trecerea 4.015 către această metodă va returna 4.01 în loc de 4.02, așa cum am văzut mai sus 4.015*100=401.499999999999994 Prin urmare, dacă vrem să facem rotunjiri precise, nu putem folosi tipuri simple pentru a face operații java.text.DecimalFormat nu rezolvă nici această problemă: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); Rezultatul este 4,02
BigDecimal Acest principiu este menționat și în cartea "Effective Java", float și double pot fi folosite doar pentru calcule științifice sau inginerești, iar în calculul de afaceri trebuie să folosim java.math.BigDecimal. Există 4 moduri de a construi BigDecimal, nu ne pasă de cele două făcute cu BigInteger, deci mai sunt două, și anume: BigDecimal (dublu val) Traduce un dublu într-un BigDecimal. BigDecimal (val de șir) Traduce reprezentația String a unui BigDecimal într-un BigDecimal.
API-ul este descris pe scurt și este de obicei mai ușor de folosit. Poate îl folosim fără să ne gândim, care ar fi problema? Când ceva mergea prost, am aflat că exista un astfel de paragraf în descrierea detaliată care dintre metodele de mai sus era suficientă: Notă: rezultatele acestui constructor pot fi oarecum imprevizibile. S-ar putea presupune că noul BigDecimal(.1) este exact egal cu 0.1, dar de fapt este egal cu .1000000000000000055511151231257827021181583404541015625. Acest lucru se datorează faptului că 0,1 nu poate fi reprezentat exact ca dublu (sau, de altfel, ca o fracție binară a oricărei lungimi finite). Astfel, valoarea lungă care este transmisă constructorului nu este exact egală cu 0,1, indiferent de aparențe. Constructorul (String), pe de altă parte, este perfect predictibil: noul BigDecimal(".1") este exact egal cu 0.1, așa cum te-ai aștepta. Prin urmare, se recomandă în general ca constructorul (String) să fie folosit în locul acestuia.
Se pare că, dacă trebuie să calculăm corect, trebuie să folosim String pentru a crea BigDecimal! Exemplul din cartea Effective Java folosește String pentru a crea BigDecimal, dar cartea nu subliniază acest lucru, ceea ce poate fi o mică greșeală.
Soluție Acum că am rezolvat această problemă, principiul este să folosești BigDecimal și să te asiguri că folosești String. Dar imaginează-ți că vrem să facem o operație de adunare, trebuie mai întâi să convertim două numere în virgulă mobilă în String, apoi să creăm un BigDecimal, să apelăm metoda de adunare pe unul dintre ele, să trecem celălalt ca argument și apoi să convertim rezultatul operației (BigDecimal) într-un număr în virgulă mobilă. Poți suporta un proces atât de obositor? Mai jos oferim o clasă de unelte Arith pentru a simplifica funcționarea. Oferă următoarele metode statice, inclusiv adunare, scădere, înmulțire și împărțire, precum și rotunjire: Public static double add (double v1, double v2) Public static double sub(double v1, double v2) Public static Double Mul(double v1, double v2) public static double div(double v1, double v2) Public static double div (double v1, double v2, int scale) Dublă rundă statică publică (dublu v, scală INT)
Anexă
Fișierul sursă Arith.java:
import java.math.BigDecimal; /** * Deoarece tipurile simple din Java nu pot executa cu precizie operații în virgulă mobilă, această clasă de unelte oferă amenzi * Operații exacte în virgulă mobilă, inclusiv adunare, scădere, înmulțire, împărțire și rotunjire. */
clasa publică Arith{
Acuratețea implicită a operațiunilor împărțite INT Static Privat Final DEF_DIV_SCALE = 10;
Această clasă nu poate fi instanțiată privat Arith(){ }
/** * Oferă operații precise de adunare. * @param se adaugă v1 * @param adăugare v2 * @return Suma celor doi parametri */
public static double add(double v1,double v2){ BigDecimal b1 = noul BigDecimal(Double.toString(v1)); BigDecimal b2 = noul BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); }
/** * Oferă operațiuni precise de scădere. * @param v1 este scăzut * @param v2 minus * @return Diferența dintre cei doi parametri */
public static double sub(double v1,double v2){ BigDecimal b1 = noul BigDecimal(Double.toString(v1)); BigDecimal b2 = noul BigDecimal(Double.toString(v2)); returnează b1.subtract(b2).doubleValue(); }
/** * Oferă operații precise de înmulțire. * @param v1 se înmulțește * @param multiplicator v2 * @return Produsul celor doi parametri */
public static double mul(double v1,double v2){ BigDecimal b1 = noul BigDecimal(Double.toString(v1)); BigDecimal b2 = noul BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); }
/** * Oferă operațiuni de divizare (relativ) exacte, atunci când are loc o divizare inepuizabilă * 10 zecimale și următoarele cifre sunt rotunjite. * @param v1 este divizat * @param divizor v2 * @return Raportul dintre cei doi parametri */
public static double div(double v1,double v2){ divizie de retur (v1,v2,DEF_DIV_SCALE); }
/** * Oferă operațiuni de divizie (relativ) exacte. Când apare o situație inepuizabilă, aceasta este indicată de parametrul scalei * Determină acuratețea, iar numerele după aceasta vor fi rotunjite. * @param v1 este divizat * @param divizor v2 * @param scară indică faptul că trebuie să fie precisă la câteva zecimale. * @return Raportul dintre cei doi parametri */
public static double div(double v1,double v2,int scale){ if(scale<0){ aruncă un nou IllegalArgumentException( "Scara trebuie să fie un întreg pozitiv sau zero"); } BigDecimal b1 = noul BigDecimal(Double.toString(v1)); BigDecimal b2 = noul BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Oferă rotunjirea zecimală precisă. * @param v necesită rotunjirea numerelor * @param scară este rezervată după punctul zecimal * @return Rezultate rotunjite */
Rundă dublă statică publică(dublu v,int scală){ if(scale<0){ aruncă un nou IllegalArgumentException( "Scara trebuie să fie un întreg pozitiv sau zero"); } BigDecimal b = noul BigDecimal(Double.toString(v)); BigDecimal unu = noul BigDecimal("1"); returnează b.divide(unu,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Precedent:Este mai bine să nu setezi un șir cu sens ca cheie primarăUrmător:Diferențe și conexiuni între JDK, JRE, JVM
|