|
|
Közzétéve 2015. 04. 07. 14:53:05
|
|
|

Nagy számok műveletosztályai java-ban elérhetők, nevezetesen a java.math.BinInteger osztály és a java.math.BigDecimal osztály. Ezeket a két osztályt használják nagy pontosságú számításokhoz, ahol a BigInteger osztály a nagy egész számok feldolgozási osztálya, míg a BigDecimal osztály a nagy és kis számok feldolgozási osztálya. Az alábbiakban bemutatjuk a BigDecimal osztályt: A BigDecimal megvalósítása kihasználja a BigInteger-t, kivéve, hogy a BigDecimal hozzáadja a tizedesszámok fogalmát. Az általános lebegő és kettős típusú adatok csak tudományos vagy mérnöki számításokhoz használhatók, mivel a kereskedelmi számítástechnikában a szükséges numerikus pontosság viszonylag magas, ezért a java.math.BigDecimal osztályt használják, amely bármilyen fix pontpontosságot támogat, és pontosan kiszámítható valutaértékek. Az alábbiakban röviden bemutatjuk a használatát példákkal
java.math.BigDecimal
Ma írtam egy programot a bináris és tizedes átalakításról a tankönyv alapján, és a program algoritmusa nem nehéz, de írás után rájöttem, hogy akár 2-től 10-ig, akár 10-től 2-ig, nem jó átalakítás 2,1 milliárdnál nagyobb számokra, vagyis többre, mint az egész számok tartománya. 0 lesz. A referenciakönyvek kimutatták, hogy a BigInteger használata megoldja ezt a problémát. Szóval utánanéztem a JDK-nak, majd többször is teszteltem, és végül sikeresen megírtam! A használati élmény a következő:
1. BigInteger a java.math.BigIntegerhez tartozik, ezért minden használat előtt importáljuk ezt az osztályt. Néha elfelejtettem az elején importálni, így a prompt nem található a folyamatos promptban.
2. Számos építési módszer létezik, de ma már alkalmanként alkalmazzák őket: BigInteger (String val) A BigInteger tizedes string reprezentációját BigInteger-re alakítsuk. BigInteger(String val, int radix) Átalakítja a megadott kardinalitásnál a BigInteger string reprezentációját a BigIntegerre. Az int típusú 2 BigInteger típussá való átalakításához írjuk BigInteger kettő=új BigInteger("2") formáját; Megjegyzés 2: a dupla idézőjeleket nem hagyhatjuk ki
3. A BigInteger osztály szimulálja az összes int-típusú matematikai műveletet, mint például add()=="+", divide()=="-" stb., de fontos megjegyezni, hogy tartalmát nem lehet közvetlenül felhasználni matematikai műveletekhez matematikai műveletek során, és a belső módszereit kell használnia. És az operandjának is BigInteger típusúnak kell lennie. Például: two.add(2) hibás művelet, mert 2 nem válik BigInteger típusba.
4. Amikor a számítási eredményeket ki akarod adni, a .toString módszerrel kell átalakítani azt tizedes láncsorrá, az alábbiak szerint részletezve: String toString() Visszaadja ennek a BigIntegernek a tizedes string reprezentációját. Kimeneti módszer: System.out.print(two.toString());
5. Magyarázd el a három használt funkciót. BigInteger maradvány (BigInteger val) Egy BigIntex-et ad vissza, amelynek értéke (ez a % val). BigInteger negate() A BigInteger (-ez) értéket ad vissza. int compareTo(BigInteger val) Hasonlítsuk össze ezt a BigIntegér-t a megadott BigIntegerrel. a maradék megtalálására szolgált. a negate az operandot az ellenkezőjévé változtatja. Az összehasonlítás részletesen a következőképpen magyarázatot kap: összehasonlítással
public int compareTo(BigInteger val)
Hasonlítsuk össze ezt a BigIntegér-t a megadott BigIntegerrel. Ezt a módszert a hat Boole-összehasonlító operátor mindegyikére (<, ==, >, >=, !=, <=) preferálják. Az összehasonlítások elvégzésére javasolt állítás: (x.compareTo(y) <op> 0), ahol a <op> hat összehasonlító operátor egyike.
Specifikátor: <BigInteger> Interfész Összehasonlítható
Paraméterek: val – Az a BigIntok, amely összehasonlítja ezt a BigIntegérrel. Hátra:
Cím: Pontos lebegőpontos számítások megvalósítása Java-ban: Eredeti módosítás Kulcsszavak: Java lebegőpontos számszámítás
Feltett kérdés: Mit látnánk, ha lefordítanánk és futtatnánk a következő programot? public class Teszt{ 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); } };
Jól olvastad! Az eredmény valóban így 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Egyszerű lebegő és dupla típusok Java-ban nem működtethetők. Ez a probléma nemcsak a Java-ban fordul elő, hanem sok más programozási nyelvben is. A legtöbb esetben a számítások pontosak, de megpróbálhatsz még néhányszor (akár egy hurkot is csinálhatsz), hogy ilyen hibákat találj, mint a fent. Most végre megértem, miért van BCD kód. Ez a probléma elég komoly, ha 9,9999999999999999999999999999999999999999999999999999999999 jüanod van, a számítógéped nem gondolja úgy, hogy 10 jüánért vásárolhatsz árut. Néhány programozási nyelv speciális valutatípusokat kínál ennek a helyzetnek a kezelésére, de a Java nem. Most nézzük meg, hogyan lehet ezt megoldani.
Kerekítés Az első reakciónk a körözés volt. A Matematika órán a kör módszert nem lehet beállítani néhány tizedesjegyre, csak ezt tudjuk megtenni (két helyet tartunk): Public double round(double value){ return Math.round(value*100)/100.0; }
Sajnos a fenti kód nem működik, a 4.015-ös verzió átvitele erre a módszerre 4.01-et ad vissza a 4.02 helyett, ahogy fentebb láttuk 4.015*100=401.4999999999999 Ezért, ha pontos kerekítést akarunk végezni, nem használhatunk egyszerű típusokat semmilyen művelethez A java.text.DecimalFormat ezt a problémát sem oldja meg: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); A kimenet 4,02
BigDecimal Ezt az elvet az "Effective Java" című könyvben is említik, a float és a double csak tudományos vagy mérnöki számításokhoz használható, az üzleti számítástechnikában pedig java.math.BigDecimal funkciót kell használni. Négy módja van a BigDecimal építésének, nem érdekel minket a BigInteger-rel készült kettő, így van még kettő, amelyek a következők: BigDecimal (dupla val) A kettőt BigDecimal-ra fordítja. BigDecimal (String val) A Nagydecimális String repre sentációját BigDecimalrá fordítja.
Az API röviden le van írva, és általában könnyebb használni. Lehet, hogy nem is gondolkodunk rajta, mi lesz a probléma? Amikor valami rosszul sült el, kiderült, hogy van egy ilyen bekezdés a részletes leírásban, amely arról, melyik fent említett módszer elegendő: Megjegyzés: ennek a konstruktornak az eredményei kissé kiszámíthatatlanok lehetnek. Feltételezhetnénk, hogy az új BigDecimal(.1) pontosan egyenlő .1-gyel, de valójában egyenlő .1000000000000000055511151231257827021181583404541015625-vel. Ez azért van, mert a .1 nem pontosan ábrázolható duplázatként (vagy akár bináris törtként, bármilyen véges hosszúsággal). Így a konstruktornak átjutott hosszú érték nem pontosan egyenlő 0,1-gyel, függetlenül a megjelenésektől. A (String) konstruktor viszont tökéletesen kiszámítható: az új BigDecimal(".1") pontosan egyenlő .1-gyel, ahogy várható lenne. Ezért általában ajánlják, hogy a (String) konstruktort használják előnyben ezzel szemben.
Kiderült, hogy ha pontosan kell számolnunk, akkor Stringet kell használnunk a BigDecimal létrehozásához! Az Effective Java című könyvben szereplő példa Stringet használ a BigDecimal létrehozásához, de a könyv ezt nem hangsúlyozza, ami talán egy apró hiba.
Megoldás Most, hogy megoldottuk ezt a problémát, az elv, hogy a BigDecimal-t használjuk, és mindenképp a String-et használjuk. De képzeld el, hogy ha összeadási műveletet akarunk végezni, először két lebegőpontos számot String-re kell alakítanunk, majd létrehoznunk egy BigDecimal-t, az egyiken az összeadási módszert hívjuk, a másikat argumentumként adjuk át, majd a művelet eredményét (BigDecimal) lebegőpontos számmá kell alakítani. Ki tudsz viselni egy ilyen fárasztó folyamatot? Az alábbiakban egy Arith eszközosztályt adunk rendelkezésre, hogy egyszerűsítsük a műveletet. A következő statikus módszereket kínálja, beleértve az összeadást, kivonást, szorzást és osztást, valamint kerekítést: Public static double add (double v1, double v2) Nyilvános statikus dupla sub (dupla v1, dupla v2) Nyilvános statikus dupla mul (dupla v1, dupla v2) Public Static Double Div (double v1, double v2) Public Static Double Div (dupla v1, dupla v2, int skala) Nyilvános statikus dupla kör (dupla V, INT skálák)
Melléklet
Forrásfájl Arith.java:
importál java.math.BigDecimal; /** * Mivel a Java egyszerű típusai nem tudják pontosan végrehajtani a lebegőpontos műveleteket, ez az eszközosztály bírságokat biztosít * Pontos lebegőpontos műveletek, beleértve az összeadást, kivonást, szorzást, osztást és kerekítést. */
public class Arith{
Alapértelmezett osztási műveleti pontosság magán statikus végső infarkt DEF_DIV_SCALE = 10;
Ez az osztály nem instantizálható private Arith(){ }
/** * Pontos összeadási műveleteket biztosít. * @param v1 hozzáadódik * @param v2 kiegészítés * @return A két paraméter összege */
Public Static double add(double v1,double v2){ BigDecimal b1 = új BigDecimal (Double.toString(v1)); BigDecimal b2 = új BigDecimal (Double.toString(v2)); return b1.add(b2).doubleValue(); }
/** * Precíz kivonási műveleteket biztosít. * @param v1 levonva * @param v2 mínusz * @return A két paraméter közötti különbség */
Public Static Double Sub(double v1,double v2){ BigDecimal b1 = új BigDecimal (Double.toString(v1)); BigDecimal b2 = új BigDecimal (Double.toString(v2)); return b1.subtract(b2).doubleValue(); }
/** * Pontos szorzási műveleteket biztosít. * @param v1 megszorozódik * @param v2 szorzó * @return A két paraméter szorzata */
Public Static double mul(double v1,double v2){ BigDecimal b1 = új BigDecimal (Double.toString(v1)); BigDecimal b2 = új BigDecimal (Double.toString(v2)); return b1.multiply(b2).doubleValue(); }
/** * Viszonylag pontos osztási műveleteket biztosít, amikor kimeríthetetlen felosztás történik * 10 tizedesszámot és a következő számjegyeket kerekítve. * @param v1 megosztott * @param v2 osztó * @return A két paraméter hányadosai */
Public Static Double Div(double v1,double v2){ visszaforduló div(v1,v2,DEF_DIV_SCALE); }
/** * Viszonylag pontos hadosztályműveleteket biztosít. Amikor kimeríthetetlen helyzet történik, azt a skálaparaméter jelzi * Határozd meg a pontosságot, és a számokat, amelyeket a lekerekítés után kapunk. * @param v1 megosztott * @param v2 osztó * @param skála azt mutatja, hogy néhány tizedesjegyig kell pontosnak lennie. * @return A két paraméter hányadosai */
Public static double div(double v1,double v2,int scale){ if(scale<0){ dobj új illegalArgumentException( "A skála pozitív egész szám vagy nulla legyen"); } BigDecimal b1 = új BigDecimal (Double.toString(v1)); BigDecimal b2 = új BigDecimal (Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Pontos tizedes kerekítést biztosít. * @param v esetén a számok kerekítése szükséges * @param skála a tizedespont után van fenntartva. * @return Kerekített eredmények */
Public Static double round(double v,int scale){ if(scale<0){ dobj új illegalArgumentException( "A skála pozitív egész szám vagy nulla legyen"); } BigDecimal b = új BigDecimal(Double.toString(v)); BigDecimal one = új BigDecimal ("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Előző:A legjobb, ha nem egy jelentéssel rendelkező húrt állítunk be elsődleges hangnemnekKövetkező:JDK, JRE, JVM különbségek és kapcsolatok
|