Operationsklasser för stora tal tillhandahålls i java, nämligen java.math.BinInteger-klassen och java.math.BigDecimal-klassen. Dessa två klasser används för högprecisionsberäkning, där BigInteger-klassen är bearbetningsklassen för stora heltal och BigDecimal-klassen är bearbetningsklassen för stora och små tal. Nedan presenterar vi BigDecimal-klassen: Implementeringen av BigDecimal utnyttjar BigInteger, förutom att BigDecimal lägger till begreppet decimaler. Allmänna flyttal- och dubbeltypdata kan endast användas för vetenskapliga eller tekniska beräkningar, eftersom den numeriska noggrannheten är relativt hög inom kommersiell databehandling, så klassen java.math.BigDecimal används, som stöder alla fixpunkter och kan användas för att exakt beräkna valutavärden. Nedan kommer vi kort att introducera dess användning med exempel
java.math.BigDecimal
Idag skrev jag ett program om binär och decimalkonvertering med hänvisning till läroboken, och programalgoritmen är inte svår, men efter att ha skrivit upptäckte jag att oavsett om det är 2 till 10 eller 10 till 2, är det inte en bra konvertering för tal större än 2,1 miljarder, det vill säga mer än heltalsintervallet. kommer att bli 0. Referensböcker har funnit att användning av BigInteger löser detta problem. Så jag kollade upp JDK:n, testade den flera gånger och skrev den till slut framgångsrikt! Användningsupplevelsen är följande:
1. BigInteger tillhör java.math.BigInteger, så importera denna klass innan varje användning. Ibland glömde jag att importera i början, så prompten kan inte hittas i den konstanta prompten.
2. Det finns många byggmetoder, men nu används de ibland: BigInteger (Strängval) Konvertera den decimala strängrepresentationen av BigInteger till BigInteger. BigInteger (Strängval, int radix) Konverterar strängrepresentationen av BigInteger för den specificerade kardinaliteten till BigInteger. För att konvertera 2 av int-typ till BigInteger-typ, skriv BigInteger two=new BigInteger("2"); Not 2: dubbla citattecken får inte utelämnas
3. BigInteger-klassen simulerar alla int-typ matematiska operationer, såsom add()=="+", divide()=="-", etc., men notera att dess innehåll inte kan användas direkt för matematiska operationer vid matematiska operationer, och måste använda dess interna metoder. Och dess operand måste också vara av typen BigInteger. Till exempel: two.add(2) är en felaktig operation eftersom 2 inte blir en BigInteger-typ.
4. När du vill ge ut beräkningsresultaten bör du använda .toString-metoden för att omvandla dem till en decimalsträng, enligt följande: String toString() Returnerar den decimalsträngsrepresentationen för detta BigInteger. Utdatametod: System.out.print(two.toString());
5. Förklara de tre funktioner som används. BigInteger rest(BigInteger val) Returnerar ett BigInteger med värdet (denna % val). BigInteger-negate() BigInteger returnerar värdet (-detta). int compareTo(BigInteger val) Jämför detta BigInteger med det specificerade BigInteger. rester används för att hitta resten. Negate förvandlar operanden till motsatsen. Jämförelsen förklaras i detalj enligt följande: jämföraMed
public int compareTo(BigInteger val)
Jämför detta BigInteger med det specificerade BigInteger. Denna metod föredras för var och en av de sex booleska jämförelseoperatorerna (<, ==, >, >=, !=, <=). Det föreslagna påståendet för att utföra dessa jämförelser är: (x.compareTo(y) <op> 0), där är <op> en av de sex jämförelseoperatorerna.
Specifierare: <BigInteger> Gränssnitt Jämförbart
Parametrar: val - Det stora heltal som jämför detta stora heltal med det. Bak:
Titel Implementering av precisa beräkningar av flyttal i Java AYellow (ursprunglig) modifiering Nyckelord Java flyttalsberäkning
Fråga ställd: Vad skulle vi se om vi kompilerade och körde följande program? offentlig klass 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); } };
Du läste rätt! Resultatet är verkligen, 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Enkla float- och dubbeltyper i Java kan inte användas. Detta problem finns inte bara i Java, utan även i många andra programmeringsspråk. I de flesta fall är beräkningarna exakta, men du kan försöka några gånger till (du kan göra en loop) för att göra fel som det ovan. Nu förstår jag äntligen varför det finns en BCD-kod. Detta problem är ganska allvarligt, om du har 9,9999999999999999999999999999999 yuan kommer din dator inte att tro att du kan köpa varor för 10 yuan. Vissa programmeringsspråk erbjuder specialiserade valutatyper för att hantera denna situation, men Java gör det inte. Nu ska vi se hur vi kan lösa detta.
Avrundning Vår första reaktion är att göra rundningar. Rundmetoden i matematikklassen kan inte sättas att behålla några decimaler, vi kan bara göra detta (behålla två platser): Offentlig dubbelrunda(dubbel värde){ returnera Math.round(value*100)/100.0; }
Tyvärr fungerar inte koden ovan, om man skickar in 4.015 till denna metod kommer det att returnera 4.01 istället för 4.02, som vi såg ovan 4.015*100=401.4999999999999994 Därför, om vi vill göra noggrann avrundning, kan vi inte använda enkla typer för att utföra några operationer java.text.DecimalFormat löser inte heller detta problem: System.out.println(ny java.text.DecimalFormat("0.00").format(4.025)); Utgången är 4,02
BigDecimal Denna princip nämns också i boken "Effective Java", float och double kan endast användas för vetenskapliga eller tekniska beräkningar, och inom affärsberäkningar behöver vi använda java.math.BigDecimal. Det finns fyra sätt att bygga BigDecimal, vi bryr oss inte om de två som görs med BigInteger, så det finns två till, nämligen: BigDecimal (dubbelval) Översätter en dubbel till en BigDecimal. BigDecimal (Strängval) Översätter strängre-sändningen för en BigDecimal till en BigDecimal.
API:et beskrivs kort och är vanligtvis enklare att använda. Vi kan använda den utan att ens tänka efter, vad blir problemet? När något gick fel upptäckte jag att det fanns ett sådant stycke i den detaljerade beskrivningen av vilka av ovanstående metoder som var tillräckliga: Notera: resultaten från denna konstruktör kan vara något oförutsägbara. Man kan anta att nya BigDecimal(.1) är exakt lika med .1, men det är faktiskt lika med .1000000000000000055511151231257827021181583404541015625. Detta beror på att 0,1 inte kan representeras exakt som en dubbel (eller, för den delen, som en binär bråkdel av någon ändlig längd). Således är det långa värde som skickas in i konstruktören inte exakt lika med 0,1, oavsett förekomster. (Sträng)konstruktorn, å andra sidan, är helt förutsägbar: ny BigDecimal(".1") är exakt lika med .1, som man kan förvänta sig. Därför rekommenderas det generellt att (String)-konstruktören används istället för denna.
Det visar sig att om vi behöver räkna noggrant, måste vi använda String för att skapa BigDecimal! Exemplet i boken Effective Java använder String för att skapa BigDecimal, men boken betonar inte detta, vilket kan vara ett litet misstag.
Lösning Nu när vi har löst detta problem är principen att använda BigDecimal och se till att använda String. Men föreställ dig att om vi vill göra en additionsoperation behöver vi först konvertera två flyttalstal till sträng, sedan skapa en BigDecimal, anropa adderingsmetoden på det ena, skicka det andra som ett argument och sedan konvertera resultatet av operationen (BigDecimal) till ett flyttalstal. Klarar du av en så tråkig process? Nedan tillhandahåller vi en verktygsklass Arith för att förenkla operationen. Den erbjuder följande statiska metoder, inklusive addition, subtraktion, multiplikation och division samt avrundning: Offentlig statisk dubbel addering (dubbel v1, dubbel v2) Offentlig statisk dubbel subwoofer (dubbel v1, dubbel v2) Offentlig statisk dubbel mul (dubbel v1, dubbel v2) Offentlig statisk dubbel division (dubbel v1, dubbel v2) Offentlig statisk dubbel div (dubbel v1, dubbel v2, int-skala) Offentlig statisk dubbel runda (dubbel V, int-skala)
Bilaga
Källfil Arith.java:
importera java.math.BigDecimal; /** * Eftersom Javas enkla typer inte kan utföra flyttalsoperationer exakt, ger denna verktygsklass fina * Exakta flyttalsoperationer, inklusive addition, subtraktion, multiplikation, division och avrundning. */
offentlig klass Arith{
Standardnoggrannhet i delningsoperationer privat statisk slutgiltig int DEF_DIV_SCALE = 10;
Denna klass kan inte instansieras privat Arith(){ }
/** * Ger precisa additionsoperationer. * @param v1 läggs till * @param v2-tillägg * @return Summan av de två parametrarna */
Offentlig statisk dubbel add(dubbel v1,dubbel v2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returnera b1.add(b2).doubleValue(); }
/** * Ger precisa subtraktionsoperationer. * @param v1 subtraheras * @param v2 minus * @return Skillnaden mellan de två parametrarna */
Offentlig statisk dubbel sub(dubbel v1,dubbel v2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returnera b1.subtraher(b2).doubleValue(); }
/** * Ger precisa multiplikationsoperationer. * @param v1 multipliceras * @param v2-multiplikator * @return Produkten av de två parametrarna */
Public Static Double MUL(Double V1,Double V2){ BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returnera b1.multiplicera(b2).doubleValue(); }
/** * Ger (relativt) exakta divisionsoperationer när outtömlig division inträffar * 10 decimaler och följande siffror avrundas. * @param v1 delas * @param v2-divisor * @return Kvoten av de två parametrarna */
Public Static Double Div(Double V1,Double V2){ return div(v1,v2,DEF_DIV_SCALE); }
/** * Tillhandahåller (relativt) exakta divisionsoperationer. När en outtömlig situation uppstår indikeras den med skalparametern * Bestäm noggrannheten, och siffrorna efter den kommer att avrundas. * @param v1 delas * @param v2-divisor * @param skala anger att den måste vara exakt med några decimaler. * @return Kvoten av de två parametrarna */
Offentlig statisk dubbel div(dubbel v1,dubbel v2,int-skala){ if(scale<0){ kasta nytt IllegalArgumentException( "Skalan måste vara ett positivt heltal eller noll"); } BigDecimal b1 = ny BigDecimal(Double.toString(v1)); BigDecimal b2 = ny BigDecimal(Double.toString(v2)); returnera b1.Divida(b2,skala,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Ger exakt decimalavrundning. * @param v kräver avrundningstal * @param skala reserveras efter decimalpunkten * @return Avrundade resultat */
offentlig statisk dubbel runda (dubbel v,int-skala){ if(scale<0){ kasta nytt IllegalArgumentException( "Skalan måste vara ett positivt heltal eller noll"); } BigDecimal b = ny BigDecimal(Double.toString(v)); BigDecimal ett = ny BigDecimal ("1"); returnera b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |