|
|
Opslået på 07/04/2015 14.53.05
|
|
|

Operationsklasser for store tal findes i Java, nemlig java.math.BinInteger-klassen og java.math.BigDecimal-klassen. Disse to klasser bruges til højpræcisionsberegning, hvor BigInteger-klassen er behandlingsklassen for store heltal, og BigDecimal-klassen er behandlingsklassen for store og små tal. Nedenfor introducerer vi BigDecimal-klassen: Implementeringen af BigDecimal udnytter BigInteger, bortset fra at BigDecimal tilføjer begrebet decimaler. Generelle float- og dobbelttype-data kan kun bruges til videnskabelige eller ingeniørmæssige beregninger, fordi den krævede numeriske nøjagtighed i kommerciel datalogi er relativt høj, så java.math.BigDecimal-klassen anvendes, som understøtter enhver præcision af faste punkter og kan bruges til nøjagtigt at beregne valutaværdier. Nedenfor vil vi kort introducere dens anvendelse med eksempler
java.math.BigDecimal
I dag skrev jeg et program om binær og decimalkonvertering med henvisning til lærebogen, og programalgoritmen er ikke svær, men efter at have skrevet det, fandt jeg ud af, at uanset om det er 2 til 10 eller 10 til 2, er det ikke en god konvertering for tal større end 2,1 milliarder, altså mere end heltalsintervallet. vil blive 0. Referencebøger har fundet, at brugen af BigInteger løser dette problem. Så jeg slog JDK'en op, testede den flere gange og skrev den endelig med succes! Brugsoplevelsen er som følger:
1. BigInteger tilhører java.math.BigInteger, så importer denne klasse før hver brug. Af og til glemte jeg at importere i starten, så prompten kan ikke findes i konstantprompten.
2. Der findes mange byggemetoder, men nu anvendes de lejlighedsvis: BigInteger (Strengval) Konverter decimalstrengrepræsentationen af BigInteger til BigInteger. BigInteger (Strengval, int radix) Konverterer strengrepræsentationen af BigInteger for den specificerede kardinalitet til BigInteger. For at konvertere 2 af int-typen til BigInteger-typen, skriv BigInteger to=ny BigInteger("2"); Note 2: dobbelte anførselstegn kan ikke udelades
3. BigInteger-klassen simulerer alle int-type matematiske operationer, såsom add()=="+", divide()=="-" osv., men bemærk, at dens indhold ikke kan bruges direkte til matematiske operationer ved udførelse af matematiske operationer, og at dens interne metoder skal benyttes. Og dens operand skal også være af typen BigInteger. For eksempel: two.add(2) er en forkert operation, fordi 2 ikke bliver en BigInteger-type.
4. Når du vil outputte beregningsresultaterne, bør du bruge .toString-metoden til at konvertere det til en decimalstreng, som i detaljer som følger: String toString() Returnerer den decimale strengrepræsentation af dette BigInteger. Outputmetode: System.out.print(two.toString());
5. Forklar de tre funktioner, der bruges. BigInteger rest(BigInteger val) Returnerer et BigInteger med værdien (denne % val). BigInteger neger() BigInteger returnerer en værdi på (-this). int compareTo(BigInteger val) Sammenlign dette BigInteger med det specificerede BigInteger. Resterer bruges til at finde resten. Negate gør operanden til det modsatte. Sammenligningen forklares i detaljer som følger: sammenlign.
public int compareTo(BigInteger val)
Sammenlign dette BigInteger med det specificerede BigInteger. Denne metode foretrækkes for hver af de seks booleske sammenligningsoperatorer (<, ==, >, >=, !=, <=). Den foreslåede sætning til at udføre disse sammenligninger er: (x.compareTo(y) <op> 0), hvor er <op> en af de seks sammenligningsoperatorer.
Specifikation: <BigInteger> Interface Sammenlignelig
Parametre: val - Det store heltal, der sammenligner dette store heltal med det. Tilbage:
Titel Implementering af præcise beregninger af flydende kommatal i Java AYellow (Original) Modifikation Nøgleord Java flydende kommatal-præcis beregning
Spørgsmål stillet: Hvad ville vi se, hvis vi kompilerede og kørte det følgende program? public class Test{ offentlig statisk 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); } };
Du læste rigtigt! Resultatet er, at det er rigtigt 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Simple float- og dobbelttyper i Java kan ikke betjenes. Dette problem findes ikke kun i Java, men også i mange andre programmeringssprog. I de fleste tilfælde er beregningerne præcise, men du kan prøve et par gange mere (du kan lave en loop) for at lave fejl som den ovenfor. Nu forstår jeg endelig, hvorfor der findes en BCD-kode. Dette problem er ret alvorligt, hvis du har 9,9999999999999999999999999999999 yuan, vil din computer ikke tro, at du kan købe varer for 10 yuan. Nogle programmeringssprog tilbyder specialiserede valutatyper til at håndtere denne situation, men Java gør ikke. Lad os nu se, hvordan vi løser det.
Afrunding Vores første reaktion er at lave runding. Rundmetoden i matematikklassen kan ikke sættes til at holde et par decimaler, vi kan kun gøre dette (beholde to pladser): offentlig dobbelt runde(dobbelt værdi){ returner Math.round(value*100)/100.0; }
Desværre virker ovenstående kode ikke; hvis man sender 4.015 til denne metode, vil det returnere 4.01 i stedet for 4.02, som vi så ovenfor 4.015*100=401.4999999999999994 Derfor, hvis vi vil lave præcis afrunding, kan vi ikke bruge simple typer til at udføre nogen operationer java.text.DecimalFormat løser heller ikke dette problem: System.out.println(ny java.text.DecimalFormat("0.00").format(4.025)); Outputtet er 4,02
BigDecimal Dette princip nævnes også i bogen "Effective Java", float og double kan kun bruges til videnskabelige eller tekniske beregninger, og i erhvervscomputing skal vi bruge java.math.BigDecimal. Der er 4 måder at bygge BigDecimal på, vi er ligeglade med de to, der laves med BigInteger, så der er to mere, som er: BigDecimal (dobbelt val) Oversætter en dobbelt til en BigDecimal. BigDecimal (Strengval) Oversætter strengens repre-sætning for en BigDecimal til en BigDecimal.
API'et beskrives kort og er som regel nemmere at bruge. Vi kan bruge det uden at tænke over det, hvad bliver problemet? Da noget gik galt, fandt jeg ud af, at der var et sådant afsnit i den detaljerede beskrivelse af, hvilken af ovenstående metoder der var tilstrækkelig: Bemærk: resultaterne af denne konstruktør kan være noget uforudsigelige. Man kunne antage, at den nye BigDecimal(.1) er præcis lig med .1, men den er faktisk lig med .1000000000000000055511151231257827021181583404541015625. Dette skyldes, at 0,1 ikke kan repræsenteres præcist som en dobbelt (eller for den sags skyld som en binær brøkdel af en endelig længde). Dermed er den lange værdi, der sendes ind i konstruktøren, ikke præcist lig med 0,1, uanset udseendet. (String)-konstruktøren er derimod fuldstændig forudsigelig: den nye BigDecimal(".1") er præcis lig med .1, som man kunne forvente. Derfor anbefales det generelt, at (Streng)-konstruktøren bruges frem for denne.
Det viser sig, at hvis vi skal beregne nøjagtigt, skal vi bruge String til at skabe BigDecimal! Eksemplet i bogen Effective Java bruger String til at skabe BigDecimal, men bogen understreger ikke dette, hvilket kan være en lille fejl.
Løsning Nu hvor vi har løst dette problem, er princippet at bruge BigDecimal og sørge for at bruge String. Men forestil dig, at hvis vi vil lave en additionsoperation, skal vi først konvertere to flydende kommatal til streng, derefter oprette en BigDecimal, kalde add-metoden på det ene af dem, sende det andet som et argument, og derefter konvertere resultatet af operationen (BigDecimal) til et flydende kommatal. Kan du holde ud en så kedelig proces? Nedenfor giver vi en værktøjsklasse Arith for at forenkle operationen. Den tilbyder følgende statiske metoder, herunder addition, subtraktion, multiplikation og division samt afrunding: offentlig statisk dobbelt add (dobbelt v1, dobbelt v2) Offentlig statisk dobbelt sub (dobbelt v1, dobbelt v2) offentlig statisk dobbelt mul (dobbelt v1, dobbelt v2) offentlig statisk dobbelt div (dobbelt v1, dobbelt v2) offentlig statisk dobbelt div (dobbelt v1, dobbelt v2, int-skala) offentlig statisk dobbelt runde (dobbelt V, INT skala)
Bilag
Kildefil Arith.java:
import java.math.BigDecimal; /** * Da Javas simple typer ikke nøjagtigt kan udføre flydende kommatal-operationer, giver denne værktøjsklasse fines * Præcise flydende kommatal-operationer, herunder addition, subtraktion, multiplikation, division og afrunding. */
offentlig klasse Arith{
Standard divisionsoperationnøjagtighed privat statisk slutint DEF_DIV_SCALE = 10;
Denne klasse kan ikke instansieres privat Arith(){ }
/** * Giver præcise additionsoperationer. * @param v1 tilføjes * @param v2-tilføjelse * @return Summen af de to parametre */
offentlig statisk dobbelt add(dobbelt v1,dobbelt v2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returner b1.add(b2).doubleValue(); }
/** * Giver præcise subtraktionsoperationer. * @param v1 trækkes fra * @param v2 minus * @return Forskellen mellem de to parametre */
offentlig statisk dobbelt sub(dobbelt v1,dobbelt v2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returner b1.subtract(b2).doubleValue(); }
/** * Giver præcise multiplikationsoperationer. * @param v1 ganges * @param v2 multiplikator * @return Produktet af de to parametre */
offentlig statisk dobbelt mul(dobbelt v1,dobbelt v2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returner b1.multiplicer(b2).doubleValue(); }
/** * Giver (relativt) præcise divisionsoperationer, når uudtømmelig division forekommer * 10 decimaler og følgende cifre rundes. * @param v1 er delt * @param v2 divisor * @return Kvotienten af de to parametre */
offentlig statisk dobbelt div(dobbelt v1,dobbelt v2){ return div(v1,v2,DEF_DIV_SCALE); }
/** * Leverer (relativt) nøjagtige divisionsoperationer. Når en uudtømmelig situation opstår, angives det af skalaparameteren * Bestem nøjagtigheden, og tallene efter den vil blive rundet. * @param v1 er delt * @param v2 divisor * @param skala angiver, at den skal være nøjagtig til et par decimaler. * @return Kvotienten af de to parametre */
offentlig statisk dobbelt div(dobbelt v1,dobbelt v2,int-skala){ if(scale<0){ smid ny IllegalArgumentException( "Skalaen skal være et positivt heltal eller nul"); } BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returner b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Giver præcis decimalafrunding. * @param v kræver afrunding af tal * @param skala reserveres efter decimalpunktet * @return Afrundede resultater */
offentlig statisk dobbelt rund(dobbelt v,int skala){ if(scale<0){ smid ny IllegalArgumentException( "Skalaen skal være et positivt heltal eller nul"); } BigDecimal b = ny BigDecimal(Double.toString(v)); BigDecimal one = ny BigDecimal("1"); returner b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Tidligere:Det er bedst ikke at sætte en streng med betydning som primærtoneartNæste:FORSKELLE OG FORBINDELSER I JDK, JRE, JVM
|