JavaRush /Java блогы /Random-KK /Java тіліндегі BigDecimal

Java тіліндегі BigDecimal

Топта жарияланған
Сәлеметсіз бе! Бүгінгі дәрісте біз үлкен сандар туралы айтатын боламыз. Жоқ, шынында да үлкендер туралы. Бұрын біз қарапайым деректер түрлеріне арналған мәндер ауқымдарының кестесін бірнеше рет көрдік. Бұл келесідей көрінеді:
Қарапайым тип Жадтағы өлшем Мәндер ауқымы
byte 8 бит -128-ден 127-ге дейін
қысқа 16 бит -32768-ден 32767-ге дейін
таңба 16 бит 0-ден 65536-ға дейін
int 32 бит -2147483648-ден 2147483647-ге дейін
ұзақ 64 бит -9223372036854775808 бастап 9223372036854775807 дейін
жүзу 32 бит (2-ден қуатқа -149) дейін ((2-2 қуатқа -23)*2 қуатқа 127)
қос 64 бит (-2-ден 63-тің дәрежесіне) ((2-нің 63-тің дәрежесі) - 1)
логикалық 8 (массивтерде пайдаланылғанда), 32 (массив еместерде пайдаланылғанда) шын немесе жалған
Егер бүтін сандар туралы айтатын болсақ, деректердің ең сыйымды түрі long , ал өзгермелі нүкте сандары туралы айтатын болсақ, double . Бірақ егер бізге қажет сан соншалықты үлкен болса, ол тіпті ұзаққа да сыймайды ? Мүмкін Long мәндерінің диапазоны өте үлкен, бірақ әлі де белгілі бір өлшеммен шектелген - 64 бит. Егер біздің өте үлкен санымыздың салмағы 100 бит болса, біз не істей аламыз? Бақытымызға орай, сізге ештеңе ойлап табудың қажеті жоқ. Java тілінде мұндай жағдайлар үшін екі арнайы класс жасалды - BigInteger (бүтін сандар үшін) және BigDecimal (жылжымалы нүктелі сандар үшін). Олардың ерекшелігі неде? Біріншіден, олардың теориялық тұрғыдан максималды мөлшері жоқ. Теориялық тұрғыдан, өйткені шексіз жады бар компьютерлер жоқ. Ал егер программада компьютердің жады көлемінен үлкен сан жасасаңыз, әрине, бағдарлама жұмыс істемейді. Бірақ мұндай жағдайлар екіталай. Сондықтан сандардың өлшемі іс жүзінде шексіз деп айта BigIntegerаламыз BigDecimal. Бұл сыныптар не үшін қолданылады? Ең алдымен, өте жоғары дәлдік талаптары бар есептеулер үшін. Мысалы, адам өмірі есептеулердің дәлдігіне байланысты болатын бағдарламалар бар (ұшақтар мен зымырандарға немесе медициналық жабдықтарға арналған бағдарламалық қамтамасыз ету). Сондықтан, тіпті 150-ші ондық бөлшек маңызды рөл атқарса, BigDecimalбұл ең жақсы таңдау. Сонымен қатар, бұл нысандар қаржы әлемінде жиі пайдаланылады, мұнда ең аз мәндерге дейін есептеулердің дәлдігі де өте маңызды. Объектілермен қалай жұмыс істеу керек BigIntegerжәне BigDecimalолар туралы нені есте сақтау маңызды? Бұл класстардың an objectілері келесідей құрылады:
public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
Жолды параметр ретінде беру мүмкін конструкторлардың бірі ғана. Here we use strings because our numbers exceed the maximum values long​​and double, and somehow we need to explain to the compiler exactly what number we want to get :) Just pass the number 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111111 will not work: Java will try to “fit” берілген нөмір қарапайым деректер түрлерінің біріне сәйкес келеді, бірақ ол олардың ешқайсысына сәйкес келмейді. Сондықтан қажетті нөмірді беру үшін жолды пайдалану жақсы нұсқа болып табылады. Екі класс да берілген жолдардан сандық мәндерді автоматты түрде шығара алады. Үлкен сандар кластарымен жұмыс істегенде есте сақтау керек тағы бір маңызды мәселе олардың an objectілерінің өзгермейтіндігі ( Immutable) . Сіз класс мысалында Stringжәне примитивтерге арналған (Integer, Long және т.б.) орауыш сыныптары бойынша өзгермейтіндік принципімен жақсы таныссыз.
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
Консоль шығысы:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Біздің нөмірлер сіз күткендей өзгерген жоқ. Қосу операциясы сәтті болуы үшін жаңа нысан жасап, оған қосу нәтижесін тағайындау керек.
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
Консоль шығысы:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Енді бәрі дұрыс жұмыс істейді :) Айтпақшы, қосу операциясының ерекше көрінетінін байқадыңыз ба?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Бұл тағы бір маңызды сәт. Үлкен санды кластар өз жұмысында +-*/ операторларын қолданбайды, оның орнына әдістер жиынтығын береді. Негізгілерін қарастырайық (әдеттегідей Oracle құжаттамасынан әдістердің толық тізімін таба аласыз: мұнда және осында ).
  1. арифметикалық амалдарды орындау тәсілдері: add() , subtract(), multiply(), divide(). Сәйкесінше қосу, алу, көбейту және бөлу амалдары үшін қолданылады.

  2. doubleValue(), intValue(), floatValue(), longValue()т.б. - Үлкен санды Java қарабайыр түріне түрлендіру үшін қолданылады. Оларды пайдалану кезінде абай болыңыз және сыйымдылық айырмашылығын есте сақтаңыз!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }

    Консоль шығысы:

    
    8198552921648689607
  3. min()және max()- берілген екі үлкен санның ең кіші және ең үлкен мәнін табуға мүмкіндік береді.
    Назар аударыңыз: әдістер статикалық емес!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }

    Консоль шығысы:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimal дөңгелектеуді басқару

Бұл тақырып бөлек бөлімге енгізілген, өйткені үлкен сандарды дөңгелектеу және оны реттеу оңай емес. BigDecimalкөмегімен сан үшін ондық таңбалардың санын орнатуға болады setScale(). Мысалы, біз 111.5555555555 санының дәлдігін үш ондық таңбаға орнатқымыз келеді. Дегенмен, біз 3 санын әдіске дәлел ретінде бере алмаймыз setScale()және осылайша өз мәселемізді шеше алмаймыз. Жоғарыда айтылғандай, BigDecimalбұл жоғары дәлдікпен есептеулерге арналған сандар. Біздің санның қазіргі түрінде 10 ондық белгісі бар. Біз олардың 7-ін алып тастап, тек 3-ін қалдырғымыз келеді. Сондықтан, 3 санына қосымша, біз параметр ретінде дөңгелектеу режимін беруіміз керек . Барлығы 8 дөңгелектеу режимі бар BigDecimal. Біршама! Бірақ егер сізге бағдарламадағы есептеулердің дәлдігін шынымен дәл баптау қажет болса, сізде бұл үшін қажет нәрсенің бәрі болады. Сонымен, мына жерде қол жетімді 8 дөңгелектеу режимі BigDecimal:
  1. ROUND_CEILING- дөңгелектеу

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- разрядты тастау

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- дөңгелектеу

    111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555

  4. ROUND_HALF_UP— үтірден кейінгі сан >= болса, дөңгелектеу.5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— үтірден кейінгі сан > ,5 болса, дөңгелектеу

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— дөңгелектеу ондық бөлшектің сол жағындағы санға байланысты болады. Егер сол жақтағы сан жұп болса, дөңгелектеу төмен қарай жүргізіледі. Ондық бөлшектің сол жағындағы сан тақ болса, ол дөңгелектенеді.

    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2

    Ондық бөлшектің сол жағындағы сан – 2 – жұп. Дөңгелектеу төмен қарай жүреді. Бізге 0 ондық таңба қажет болғандықтан, нәтиже 2 болады.

    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4

    Ондық бөлшектің сол жағындағы сан – 3 – тақ. Дөңгелектеу жоғары қарай жүреді. Бізге 0 ондық таңба қажет болғандықтан, нәтиже 4 болады.

  7. ROUND_UNNECCESSARY— дөңгелектеу режимін қандай да бір әдіске көшіру қажет, бірақ санды дөңгелектеу қажет емес жағдайларда қолданылады. ROUND_UNNECCESSARY режимі орнатылған кезде санды дөңгелектеуге әрекеттенсеңіз, ArithmeticException шығарылады.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- дөңгелектеу.

    111.5551 -> setScale(3, ROUND_UP) -> 111.556

Үлкен сандарды салыстыру

Бұл сұрақтың да маңызы зор. Бұл әдіс Java тіліндегі an objectілерді салыстыру үшін қолданылатыны есіңізде equals(). Ол тілдің өзімен қамтамасыз етіледі (Java-ның кіріктірілген сыныптары жағдайында) немесе бағдарламашы арқылы жойылады. Бірақ сынып an objectілері жағдайында салыстыру BigDecimalәдісін пайдалану ұсынылмайды. equals()Мұның себебі BigDecimal.equals()екі сандық әдіс тек екі санның мәні мен масштабы бірдей болса ғана ақиқат мәнін қайтарады: y және y әдістерінің әрекетін салыстырайық : equals()DoubleBigDecimal
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));

   }
}
Консоль шығысы:

true
false
Көріп отырғаныңыздай, с жағдайында 1,5 және 1,50 сандары BigDecimalтең емес болып шықты! equals()Бұл сыныптағы әдістің ерекшеліктеріне байланысты болды BigDecimal. Екеуін дұрыс салыстыру үшін BigDecimalмына әдісті қолданған дұрыс compareTo():
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
Консоль шығысы:

0
Әдіс compareTo()0 мәнін қайтарды, бұл 1,5 және 1,50 мәндерін білдіреді. Бұл біз күткен нәтиже! :) Осымен бүгінгі сабағымыз аяқталды. Тапсырмаларға қайтатын уақыт келді! :)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION