|
|
Objavljeno na 7. 04. 2015 14:53:05
|
|
|

V javi so na voljo operacijski razredi za velika števila, in sicer java.math.BinInteger razred in java.math.BigDecimal. Ta dva razreda se uporabljata za visoko natančno računalništvo, pri čemer je razred BigInteger razred za obdelavo velikih celih števil, razred BigDecimal pa razred za obdelavo velikih in majhnih števil. Spodaj predstavljamo razred BigDecimal: Implementacija BigDecimal izkorišča BigInteger, razen da BigDecimal doda koncept decimal. Splošni podatki o plavanju in dvojnem tipu se lahko uporabljajo le za znanstvene ali inženirske izračune, saj je v komercialnem računalništvu zahtevana numerična natančnost razmeroma visoka, zato se uporablja java.math.BigDecimal razred, ki podpira katerokoli natančnost fiksnih točk in se lahko uporablja za natančno izračunavanje vrednosti valut. Spodaj bomo na kratko predstavili njegovo uporabo s primeri
java.math.BigDecimal
Danes sem napisal program o binarnem in decimalnem pretvorbi s sklicevanjem na učbenik, in algoritem programa ni zahteven, a po pisanju sem ugotovil, da ne glede na to, ali je 2 proti 10 ali 10 proti 2, ni dobra pretvorba za števila večja od 2,1 milijarde, torej več kot celoštevilski razpon. bo postal 0. Referenčne knjige so ugotovile, da uporaba BigInteger reši ta problem. Zato sem poiskal JDK, ga večkrat preizkusil in ga končno uspešno napisal! Izkušnja uporabe je naslednja:
1. BigInteger spada v java.math.BigInteger, zato ta razred uvozimo pred vsako uporabo. Občasno sem pozabil uvoziti na začetku, zato poziva ni mogoče najti v stalnem pozivu.
2. Obstaja veliko gradbenih metod, vendar se zdaj občasno uporabljajo: BigInteger (vrednost nizov) Pretvorite decimalno predstavitev BigInteger v BigInteger. BigInteger(vrednost nizov, int radix) Pretvori nizno predstavitev BigInteger za določeno kardinalnost v BigInteger. Za pretvorbo 2 int tipa v BigInteger tip zapišemo BigInteger two=new BigInteger("2"); Opomba 2: dvojne narekovaje ni mogoče izpustiti
3. Razred BigInteger simulira vse int-tip matematične operacije, kot so add()=="+", dideli()=="-" itd., vendar upoštevajte, da njegove vsebine ni mogoče neposredno uporabiti za matematične operacije pri izvajanju matematičnih operacij in mora uporabljati svoje notranje metode. In njegov operand mora biti prav tako tipa BigInteger. Na primer: two.add(2) je nepravilna operacija, ker 2 ne postane BigInteger tip.
4. Ko želite izpisati rezultate izračuna, uporabite metodo .toString za pretvorbo v decimalni niz, podrobno kot sledi: String toString() Vrne decimalno predstavitev tega BigIntegera. Metoda izhoda: System.out.print(two.toString());
5. Pojasnite tri uporabljene funkcije. BigInteger remainder(BigInteger val) Vrne BigInteger z vrednostjo (ta % vrednost). BigInteger negate() BigInteger vrne vrednost (-to). int compareTo(BigInteger val) Primerjajte to BigInteger z določenim BigInteger. preostanek se uporablja za iskanje preostanka. Negacija spremeni operand v nasprotje. Primerjava je podrobno pojasnjena takole: compareTo
public int compareTo(BigInteger val)
Primerjajte to BigInteger z določenim BigInteger. Ta metoda je zaželena za vsak od šestih Boolovih primerjalnih operatorjev (<, ==, >, >=, !=, <=). Predlagana izjava za izvedbo teh primerjav je: (x.compareTo(y) <op> 0), kjer je <op> eden izmed šestih operatorjev primerjal.
Specifikator: vmesnik<BigInteger> Primerljiv
Parametri: val - BigInteger, ki primerja to BigInteger z njim. Nazaj:
Naslov: Izvajanje natančnih izračunov števil s plavajočo vejico v Java AYellow (izvirna) modifikacija Ključne besede Java natančen izračun števila s plavajočo vejico
Zastavljeno vprašanje: Kaj bi videli, če bi prevedli in zagnali naslednji program? javni razred 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); } };
Prav ste prebrali! Rezultat je res 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Preprostih plavajočih in dvojnih tipov v Javi ni mogoče upravljati. Ta težava ni prisotna le v Javi, ampak tudi v mnogih drugih programskih jezikih. V večini primerov so izračuni točni, lahko pa poskusite še nekajkrat (lahko naredite zanko), da poskusite napake, kot je zgornja. Zdaj končno razumem, zakaj obstaja BCD koda. Ta težava je precej resna, če imate 9,99999999999999999 juanov, vaš računalnik ne bo mislil, da lahko kupite 10 juanov blaga. Nekateri programski jeziki ponujajo specializirane vrste valut za obvladovanje teh situacij, Java pa tega ne omogoča. Zdaj pa poglejmo, kako to popraviti.
Zaokroževanje Naša prva reakcija je zaokrožitev. Metoda kroga v predmetu matematike ni nastavljena tako, da ohranja nekaj decimalnih mest, lahko naredimo le to (ohranimo dve mesti): javni dvojni krog (dvojna vrednost){ vrni Math.round(value*100)/100.0; }
Na žalost zgornja koda ne deluje, prenos 4.015 v to metodo bo vrnil 4.01 namesto 4.02, kot smo videli zgoraj 4.015*100=401.4999999999999994 Zato, če želimo natančno zaokroževanje, ne moremo uporabiti preprostih tipov za izvajanje operacij java.text.DecimalFormat tega problema prav tako ne reši: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); Izhod je 4,02
BigDecimal To načelo je omenjeno tudi v knjigi »Effective Java«; float in double se lahko uporabljata le za znanstvene ali inženirske izračune, v poslovnem računalništvu pa moramo uporabljati java.math.BigDecimal. Obstajajo štirje načini za gradnjo BigDecimal, za dva pa nas ne zanimajo, zato obstajata še dva, in sicer: BigDecimal (dvojna vrednost) Dvojno prevede v BigDecimal. BigDecimal(String val) Prevede ponovitev String iz BigDecimal v BigDecimal.
API je na kratko opisan in je običajno lažji za uporabo. Morda ga uporabimo, ne da bi o tem sploh razmišljali, kakšen bo problem? Ko je šlo kaj narobe, sem ugotovil, da je v podrobnem opisu naveden, katera od zgornjih metod je zadostovala: Opomba: rezultati tega konstruktorja so lahko nekoliko nepredvidljivi. Lahko bi predpostavili, da je nova BigDecimal(.1) natanko enaka .1, vendar je v resnici enaka .1000000000000000055511151231257827021181583404541015625. To je zato, ker .1 ni mogoče natančno predstaviti kot dvojček (ali, če smo natančni, kot binarni ulomek katere koli končne dolžine). Tako dolga vrednost, ki se prenaša konstruktorju, ni natančno enaka 0,1, ne glede na videz. Konstruktor (String) pa je popolnoma predvidljiv: novi BigDecimal(".1") je natanko enak .1, kot bi pričakovali. Zato se na splošno priporoča, da se namesto tega uporablja konstruktor (String).
Izkazalo se je, da če moramo natančno izračunati, moramo uporabiti String za ustvarjanje BigDecimal! Primer v knjigi Effective Java uporablja String za ustvarjanje BigDecimal, vendar knjiga tega ne poudarja, kar je lahko majhna napaka.
Rešitev Zdaj, ko smo ta problem rešili, je načelo, da uporabimo BigDecimal in poskrbimo, da uporabimo String. Predstavljajte si, da želimo izvesti seštevanje, najprej pretvoriti dve števili s plavajočo vejico v String, nato ustvariti BigDecimal, poklicati metodo seštevanja na eni izmed njiju, drugo poslati kot argument in nato pretvoriti rezultat operacije (BigDecimal) v številko s plavajočo vejico. Ali lahko preneseš tako dolgočasen postopek? Spodaj predstavljamo razred orodja Arith, da poenostavimo operacijo. Ponuja naslednje statične metode, vključno s seštevanjem, odštevanjem, množenjem in deljenjem ter zaokroževanjem: Javno statično dvojno dodajanje (dvojno v1, dvojno v2) Javni statični dvojni subwoofer (dvojni v1, dvojni v2) Javni statični dvojni mul (dvojni v1, dvojni v2) Javni statični dvojni razdeljevanje (dvojni V1, dvojni V2) Javni statični dvojni div (dvojni v1, dvojni v2, int lestvica) Javni statični dvojni krog (Double V, INT lestvica)
Priloga
Izvorna datoteka Arith.java:
import java.math.BigDecimal; /** * Ker preprosti tipi v Javi ne morejo natančno izvajati operacij s plavajočo vejico, ta razred orodij zagotavlja fines * Natančne operacije s plavajočo vejico, vključno s seštevanjem, odštevanjem, množenjem, deljenjem in zaokroževanjem. */
javni razred Arit{
Natančnost privzetih deljenih operacij zasebni statični končni int DEF_DIV_= 10;
Tega razreda ni mogoče instancirati zasebni Arith(){ }
/** * Omogoča natančne seštevalne operacije. * @param se doda v1 * @param v2 seštevanje * @return Vsota obeh parametrov */
javno statično dvojno seštevanje(double v1,double v2){ BigDecimal b1 = novi BigDecimal(Double.toString(v1)); BigDecimal b2 = novi BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); }
/** * Omogoča natančne operacije odštevanja. * @param v1 se odšteje * @param v2 minus * @return Razlika med obema parametroma */
javni statični dvojni sub(double v1,double v2){ BigDecimal b1 = novi BigDecimal(Double.toString(v1)); BigDecimal b2 = novi BigDecimal(Double.toString(v2)); vrni b1.subtract(b2).doubleValue(); }
/** * Omogoča natančne množilne operacije. * @param v1 se pomnoži * @param množitelj v2 * @return Produkt obeh parametrov */
javni statični double mul(double v1,double v2){ BigDecimal b1 = novi BigDecimal(Double.toString(v1)); BigDecimal b2 = novi BigDecimal(Double.toString(v2)); vrni b1.množenje(b2).doubleValue(); }
/** * Zagotavlja (relativno) natančne operacije deljenja, kadar pride do neizčrpnega deljenja * 10 decimalk in naslednje številke so zaokrožene. * @param v1 je razdeljen * @param delitelj v2 * @return Količnik obeh parametrov */
javni statični dvojni del(double v1,double v2){ return div(v1,v2,DEF_DIV_); }
/** * Zagotavlja (relativno) natančne operacije divizij. Ko pride do neizčrpne situacije, jo označi parameter skale * Določite natančnost, številke za njo pa bodo zaokrožene. * @param v1 je razdeljen * @param delitelj v2 * @param lestvici kaže, da mora biti natančen do nekaj decimal. * @return Količnik obeh parametrov */
Javni statični dvojni div (dvojni v1, dvojni v2, int lestvica){ if(<0){ throw new IllegalArgumentException( "Lestvica mora biti pozitivno celo število ali nič"); } BigDecimal b1 = novi BigDecimal(Double.toString(v1)); BigDecimal b2 = novi BigDecimal(Double.toString(v2)); return b1.divide(b2,,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Omogoča natančno decimalno zaokroževanje. * @param v zahteva zaokroževanje števil * @param lestvica je rezervirana za decimalno vejico * @return Zaokroženi rezultati */
javni statični dvojni krog (double v,int lestvica){ if(<0){ throw new IllegalArgumentException( "Lestvica mora biti pozitivno celo število ali nič"); } BigDecimal b = novi BigDecimal(Double.toString(v)); BigDecimal ena = novi BigDecimal("1"); return b.divide(one,,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Prejšnji:Najbolje je, da niza z pomenom ne postavimo kot primarni ključNaslednji:Razlike in povezave med JDK, JRE, JVM
|