|
|
Zverejnené 7. 4. 2015 14:53:05
|
|
|

V Jave sú poskytované operačné triedy pre veľké čísla, konkrétne trieda java.math.BinInteger a trieda java.math.BigDecimal. Tieto dve triedy sa používajú pre výpočty s vysokou presnosťou, pričom trieda BigInteger je trieda spracovania pre veľké celé čísla a trieda BigDecimal je trieda spracovania pre veľké a malé čísla. Nižšie predstavujeme triedu BigDecimal: Implementácia BigDecimal využíva BigInteger, okrem toho, že BigDecimal pridáva koncept desatinných čísel. Všeobecné float a double type dáta sa dajú použiť len na vedecké alebo inžinierske výpočty, pretože v komerčnom počítaní je požadovaná numerická presnosť relatívne vysoká, preto sa používa trieda java.math.BigDecimal, ktorá podporuje akúkoľvek presnosť pevných bodov a môže sa použiť na presný výpočet hodnôt meny. Nižšie stručne predstavíme jeho použitie s príkladmi
java.math.BigDecimal
Dnes som napísal program o binárnom a desatinnom prevode s odkazom na učebnicu a algoritmus programu nie je zložitý, ale po jeho napísaní som zistil, že či už je to 2 ku 10 alebo 10 ku 2, nie je to dobrý prevod pre čísla väčšie ako 2,1 miliardy, teda viac ako celočíselný rozsah. sa stane 0. Referenčné knihy zistili, že použitie BigInteger tento problém rieši. Tak som si vyhľadal JDK, potom som ho niekoľkokrát otestoval a nakoniec som ho úspešne napísal! Používateľský zážitok je nasledovný:
1. BigInteger patrí do java.math.BigInteger, preto importujte túto triedu pred každým použitím. Občas som zabudol importovať na začiatku, takže prompt sa nedá nájsť v neustálom prompte.
2. Existuje mnoho stavebných metód, ale teraz sa občas používajú: BigInteger(String val) Konvertujte reprezentáciu desatinného reťazca BigInteger na BigInteger. BigInteger(hodnota reťazca, int radix) Prevádza reťazcovú reprezentáciu BigInteger pre špecifikovanú kardinálnosť na BigInteger. Na konverziu 2 int typu na BigInteger typ zapíšte BigInteger two=new BigInteger("2"); Poznámka 2: dvojité úvodzovky nesmú byť vynechané
3. Trieda BigInteger simuluje všetky int-typ matematické operácie, ako sú add()=="+", didele()=="-", atď., ale je potrebné poznamenať, že jej obsah nie je možné priamo použiť na matematické operácie pri vykonávaní matematických operácií a musí použiť svoje interné metódy. A jeho operand musí byť tiež typu BigInteger. Napríklad: two.add(2) je nesprávna operácia, pretože 2 sa nestane typom BigInteger.
4. Keď chcete vypísať výsledky výpočtu, mali by ste použiť metódu .toString na ich konverziu na desatinný reťazec, pričom je to podrobne uvedené: String toString() Vráti desatinnú reťazcovú reprezentáciu tohto veľkého celého čísla. Výstupná metóda: System.out.print(two.toString());
5. Vysvetlite tri používané funkcie. BigInteger remainder(BigInteger val) Vráti veľké celé číslo s hodnotou (táto % hodnota). BigInteger negate() BigInteger vráti hodnotu (-this). int compareTo(BigInteger val) Porovnajte toto BigInteger so špecifikovaným BigInteger. Remainderis sa používa na nájdenie zvyšku. Negácia premení operand na opak. Porovnanie je podrobne vysvetlené nasledovne: compareTo
public int compareTo(BigInteger val)
Porovnajte toto BigInteger so špecifikovaným BigInteger. Táto metóda je preferovaná pre každý zo šiestich Booleových operátorov porovnávania (<, ==, >, >=, !=, <=). Navrhované vyjadrenie na vykonanie týchto porovnaní je: (x.compareTo(y) <op> 0), kde je <op> jedným zo šiestich operátorov porovnania.
Špecifikátor: <BigInteger> Rozhranie Porovnateľné
Parametre: val - BigInteger, ktorý porovnáva toto BigInteger s ním. Zadná časť:
Názov Implementácia presných výpočtov čísel s pohyblivou desatinnou čiarkou v Java AYellow (pôvodná) modifikácia Kľúčové slová Presný výpočet čísel s pohyblivou desatinnou čiarkou v Jave
Otázka položená: Čo by sme videli, keby sme skompilovali a spustili nasledujúci program? public class 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); } };
Čítate správne! Výsledok je naozaj 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Jednoduché float a dvojité typy v Jave nie je možné ovládať. Tento problém sa nevyskytuje len v Jave, ale aj v mnohých iných programovacích jazykoch. Vo väčšine prípadov sú výpočty presné, ale môžete skúsiť ešte párkrát (môžete spraviť slučky) a vyskúšať chyby ako je tá vyššie. Teraz konečne chápem, prečo existuje BCD kód. Tento problém je dosť vážny, ak máte 9,9999999999999999 jüanov, váš počítač si nebude myslieť, že môžete kúpiť tovar za 10 jüanov. Niektoré programovacie jazyky poskytujú špecializované typy mien na riešenie tejto situácie, ale Java nie. Teraz sa pozrime, ako to opraviť.
Zaokrúhľovanie Našou prvou reakciou je zaokrúhľovanie. Metóda zaokrúhlenia v triede matematiky sa nedá nastaviť tak, aby držala niekoľko desatinných miest, môžeme len toto (ponechať dve miesta): verejné dvojité kolo (dvojitá hodnota){ return Math.round(value*100)/100.0; }
Bohužiaľ, vyššie uvedený kód nefunguje, odoslanie 4.015 do tejto metódy vráti 4.01 namiesto 4.02, ako sme videli vyššie 4.015*100=401.499999999999994 Preto, ak chceme presné zaokrúhľovanie, nemôžeme použiť jednoduché typy na žiadne operácie java.text.DecimalFormat tento problém tiež nerieši: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); Výstup je 4,02
BigDecimal Tento princíp je spomenutý aj v knihe "Effective Java", float a double sa dajú použiť len na vedecké alebo inžinierske výpočty a v biznis computingu musíme použiť java.math.BigDecimal. Existujú 4 spôsoby, ako postaviť BigDecimal, nezáleží nám na tých dvoch, ktoré sú vytvorené pomocou BigInteger, takže existujú ďalšie dva, a to: BigDecimal (dvojitá hodnota) Prekladá dvojnásobok na veľké desatinné číslo. BigDecimal (String val) Prekladá represenciu reťazca z BigDecimal na BigDecimal.
API je stručne popísané a zvyčajne je jednoduchšie na používanie. Môžeme ho použiť bez rozmýšľania, aký bude problém? Keď sa niečo pokazilo, zistil som, že v podrobnom popise je takýto odsek, ktorý z vyššie uvedených metód je postačujúci: Poznámka: výsledky tohto konštruktora môžu byť do istej miery nepredvídateľné. Dalo by sa predpokladať, že nový BigDecimal(.1) je presne 0,1, ale v skutočnosti je rovný .1000000000000000055511151231257827021181583404541015625. Je to preto, že 0,1 nemožno presne reprezentovať ako dvojnásobok (alebo, mimochodom, ako binárny zlomok akejkoľvek konečnej dĺžky). Takže dlhá hodnota, ktorá sa prenáša do konštruktora, nie je presne rovná 0,1, bez ohľadu na vzhľad. Konštruktor (String) je naopak úplne predvídateľný: nový BigDecimal(".1") je presne rovný .1, ako by sa dalo očakávať. Preto sa všeobecne odporúča použiť konštruktor (String) namiesto tohoto.
Ukazuje sa, že ak potrebujeme presne vypočítať, musíme použiť String na vytvorenie BigDecimal! Príklad v knihe Effective Java používa reťazec na vytvorenie BigDecimal, ale kniha to nezdôrazňuje, čo môže byť malá chyba.
Riešenie Teraz, keď sme tento problém vyriešili, princíp je použiť BigDecimal a uistiť sa, že použijeme String. Ale predstavte si, že ak chceme vykonať operáciu sčítania, najprv musíme previesť dve čísla s pohyblivou desatinnou čiarkou na String, potom vytvoriť BigDecimal, zavolať metódu sčítania na jedno z nich, druhé poslať ako argument a potom výsledok operácie (BigDecimal) previesť na číslo s pohyblivou desatinnou čiarkou. Dokážete vydržať taký zdĺhavý proces? Nižšie uvádzame triedu nástrojov Arith, aby sme zjednodušili operáciu. Ponúka nasledujúce statické metódy, vrátane sčítania, odčítania, násobenia a delenia, ako aj zaokrúhľovania: Verejné statické dvojité sčítanie (dvojité v1, dvojité v2) Public Static double sub (double v1, double v2) Public Static Double Mul (Double V1, Double V2) Verejné statické dvojité rozdelenie (dvojité v1, dvojité v2) Public Static double div (double v1, double v2, int scale) Verejné statické dvojité kolo (Double V, Int stupnica)
Príloha
Zdrojový súbor Arith.java:
import java.math.BigDecimal; /** * Keďže jednoduché typy v Jave nedokážu presne vykonávať operácie s pohyblivou desatinnou čiarkou, táto trieda nástrojov poskytuje pokuty * Presné operácie s pohyblivou desatinnou čiarkou, vrátane sčítania, odčítania, násobenia, delenia a zaokrúhľovania. */
verejná trieda Arit{
Presnosť štandardnej delenia súkromný statický finálny int DEF_DIV_SCALE = 10;
Túto triedu nie je možné inštancionovať súkromný Arith(){ }
/** * Poskytuje presné operácie sčítania. * @param sa pridáva v1 * @param sčítanie v2 * @return Súčet dvoch parametrov */
Public Static double add(double v1,double v2){ BigDecimal b1 = nový BigDecimal(Double.toString(v1)); BigDecimal b2 = nový BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); }
/** * Poskytuje presné operácie odčítania. * @param v1 sa odčíta * @param v2 mínus * @return Rozdiel medzi týmito dvoma parametrami */
Public Static double sub(double v1,double v2){ BigDecimal b1 = nový BigDecimal(Double.toString(v1)); BigDecimal b2 = nový BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); }
/** * Poskytuje presné násobenie. * @param v1 sa násobí * @param násobiteľ v2 * @return Súčin oboch parametrov */
Public Static double mul(double v1,double v2){ BigDecimal b1 = nový BigDecimal(Double.toString(v1)); BigDecimal b2 = nový BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); }
/** * Poskytuje (relatívne) presné operácie delenia, keď dochádza k nevyčerpateľnému deleniu * 10 desatinných miest a nasledujúce číslice sú zaokrúhlené. * @param v1 je rozdelený * @param deliteľ v2 * @return Kvocient týchto dvoch parametrov */
Public Static double div(double v1,double v2){ return div(v1,v2,DEF_DIV_SCALE); }
/** * Zabezpečuje (relatívne) presné divízne operácie. Keď nastane nevyčerpateľná situácia, je označená parametrom mierky * Určte presnosť a čísla po nej budú zaokrúhlené. * @param v1 je rozdelený * @param deliteľ v2 * @param stupnica naznačuje, že musí byť presná na niekoľko desatinných miest. * @return Kvocient týchto dvoch parametrov */
Public Static double div(double v1, double v2, int scale){ if(scale<0){ throw new IllegalArgumentException( "Stupnica musí byť kladné celé číslo alebo nula"); } BigDecimal b1 = nový BigDecimal(Double.toString(v1)); BigDecimal b2 = nový BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Poskytuje presné desatinné zaokrúhľovanie. * @param v vyžaduje zaokrúhľovanie čísel * @param stupnica je vyhradená za desatinnou čiarkou * @return Zaokrúhlené výsledky */
verejné statické dvojité kolo (double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "Stupnica musí byť kladné celé číslo alebo nula"); } BigDecimal b = nový BigDecimal(Double.toString(v)); BigDecimal jedna = nový BigDecimal ("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Predchádzajúci:Najlepšie je nenastavovať reťazec s významom ako primárny kľúčBudúci:Rozdiely a spojenia medzi JDK, JRE, JVM
|