JavaRush /مدونة جافا /Random-AR /BigInteger وBigDecimal

BigInteger وBigDecimal

نشرت في المجموعة
في Java، يتكون التطبيق من فئات، وتتكون الفئات من أساليب ومتغيرات. وتنقسم المتغيرات بدورها إلى بدائية ومرجعية. عدد صحيح كبير وBigDecimal - 1هناك 8 أنواع من المتغيرات في Java، باستثناء booleanو char، يتم تقسيمها إلى الأنواع التالية:
  • الأعداد الصحيحة: byteو shortو intو long؛
  • النقطة العائمة (وتسمى أيضًا الأرقام الحقيقية): floatو double.
داخل هذه المجموعات الصغيرة، توجد اختلافات فقط في نطاق القيم التي يمكن احتواؤها (وبالتالي تختلف المساحة المشغولة لمثل هذا المتغير). أكبر أنواع الأعداد الصحيحة هو long، مع نطاق من -9223372036854775808 إلى 9223372036854775807. من بين أرقام الفاصلة العائمة، doubleمع نطاق من 1.7e-308 إلى 1.7e+308. يمكنك قراءة المزيد عن الأعداد الحقيقية في هذه المقالة . ولكن ماذا لو أردنا تخزين أرقام أكبر من النطاق المقبول؟ في هذه الحالة سنحتاج BigIntegerو BigDecimal.

BigInteger في جافا

يتم استخدام فئة Java BigIntegerكقيمة تناظرية للقيم الصحيحة ذات الطول التعسفي التي لا تحتوي على حد 64 بت من الطول. علاوة على ذلك، فهو سليل للفئة Number، مثل الأغلفة القياسية للأنواع الرقمية البسيطة - Integerو Longو Byteو Doubleوما إلى ذلك - وبالتالي فهو يحتوي على تطبيقات تؤدي إلى أنواع بسيطة:
BigInteger value = new BigInteger("32145");

int intValue = value.intValue();//32145

long longValue = value.longValue();//32145

double doubleValue = value.doubleValue();//32145.0
نرى على الفور إنشاء مثل هذا الكائن BigIntegerمع تمرير القيمة إلى المُنشئ، ولكن بتنسيق سلسلة. والجدير بالذكر أن لديه أكثر من مصمم ولكن لجميع المناسبات. إذا كانت الأنواع البدائية لا تستوعب الكمية الكاملة للبيانات من BigInteger، فسيتم اقتطاع البيانات إلى نطاق هذا النوع البدائي. ولكن في الوقت نفسه، هناك نظائر لهذه الأساليب ( intValueExact()، longValueExact()وما إلى ذلك)، مع الاختلاف الوحيد وهو أنه إذا كان النوع البسيط الذي يحدث التحويل إليه لا يستوعب نطاق البيانات، فسيتم طرح ArithmeticException .

ثوابت BigInteger

للاستخدام الداخلي، يحتوي الفصل على ثوابت:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
هذه كائنات ثابتة BigIntegerذات قيم، على التوالي 0، 1و 10.

طرق الأعداد الصحيحة الكبيرة

إحدى الميزات الرئيسية لهذه الفئة هي أنها مليئة بالطرق التي تنفذ العمليات الحسابية القياسية في Java. على سبيل المثال:
  • عمليات الجمع:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • عمليات الضرب:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • عمليات إيجاد الباقي عند قسمة عدد على آخر:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • الحصول على القيمة المطلقة لرقم (أي modulo، غير موقعة):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
هناك أيضًا طرق لعمليات أكثر تعقيدًا (محددة):
  • العمليات مع حساب وزارة الدفاع :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
هناك عدة أشكال مختلفة لهذه الوظيفة:
  • الحصول على رقم عشوائي وتحديد عدد البتات التي ستستخدمها القيمة الناتجة:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • عمليات التحول في اتجاه البت (هذا >> n)

    تحول اليسار:

    BigInteger firstValue = new BigInteger("5");
    BigInteger firstResultValue = firstValue.shiftLeft(3);//40

    التحول إلى اليمين:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
بالطبع، من الأفضل إلقاء نظرة على القائمة الكاملة للطرق في الوثائق . عدد صحيح كبير وBigDecimal - 2

BigDecimal في جافا

عندما نحتاج إلى عدد حقيقي من الطول التعسفي، يتم استخدام فئة Java - BigDecimal. كقاعدة عامة، يتم استخدامه للعمل مع الشؤون المالية بدلاً من ذلك double، لأنه يوفر المزيد من خيارات التخصيص. Like and BigIntegerهو BigDecimalسليل فئة وله Numberطرق تُرجع قيمة كائن كنوع بدائي محدد:
BigDecimal value = new BigDecimal(35563.3);

long longValue = value.longValue();//35563

double doubleValue = value.doubleValue();//35563.3
كما نرى عند التخفيض إلى long، يبقى الجزء الصحيح فقط، ويتم تجاهل المنازل العشرية.

المنشئون BigDecimal

سوف نلقي نظرة فاحصة على المصممين BigDecimal، حيث أن الفصل لديه مجموعة أكبر بكثير منهم. هناك منشئات تسمح لك بتعيين قيمة كائن بطرق مختلفة (عن طريق تمرير intو longو doubleو Stringو حتى BigInteger)، وهناك من يسمح بذلك. اضبط إعدادات الكائن الذي تم إنشاؤه (طرق التقريب، عدد المنازل العشرية):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
كل شيء واضح هنا، فنحن نحدد مباشرة قيمة وعدد المنازل العشرية التي نريد رؤيتها.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
يمكن أن تكون نتائج هذا المنشئ غير متوقعة تمامًا، لأننا نحدد مزدوجًا، وهو بطبيعته نوع غامض للغاية. لذلك، يوصى عمومًا باستخدامه في المُنشئ String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
لقد قمنا بتعيين doubleولكن في نفس الوقت قمنا أيضًا بتعيين معلمة تصف قاعدة التقريب (التي تحتوي على عدد المنازل العشرية وخوارزمية التقريب).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
نقوم بتعيين مصفوفة من الأحرف، ومن أي عنصر نأخذ قيم الكائن وكم عدد هذه العناصر التي نأخذها.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
نحن نأخذ كائنًا موجودًا بالفعل BigInteger، ونحدد عدد المنازل العشرية.

الأساليب العشرية الكبيرة

يحتوي الفصل BigDecimalأيضًا على طرق لمختلف العمليات الحسابية، لكنه BigIntegerلا يحتوي على طرق للتعامل مع البتات، مثل . ولكن مع ذلك، فإن الميزة الرئيسية BigDecimalهي المرونة في العمل مع أرقام الفاصلة العائمة. دعونا نلقي نظرة على بعض التقنيات التي تمنحنا القدرة على إتقان الأعداد الحقيقية:
  • نحصل على الدقة (عدد الأرقام):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • تعيين عدد المنازل العشرية وقاعدة التقريب:

    BigDecimal firstValue = new BigDecimal(3445.544445);
    
    BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545

    أدناه سنلقي نظرة فاحصة على الثوابت الخاصة بوضع قواعد التقريب.

  • القسمة BigDecimalعلى آخر BigDecimal، مع الإشارة إلى العدد المطلوب من المنازل العشرية وقاعدة التقريب:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • تحريك النقطة العشرية يمينًا/يسارًا بعدد معين من الأماكن:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • تقليم الأصفار الزائدة:

    BigDecimal value = new BigDecimal("45056.5000");
    BigDecimal result = value.stripTrailingZeros();//45056.5

    إذا كان لدينا جميع الأصفار في الجزء الحقيقي، وهناك أيضًا أصفار في الجزء بأكمله (أو ليس لدينا منازل عشرية على الإطلاق)، إذن:

    BigDecimal value = new BigDecimal("450000.000");
    BigDecimal result = value.stripTrailingZeros();//4.5E+5

قواعد التقريب BigDecimal

لتعيين قواعد التقريب، BigDecimalيمكننا أن نرى في الداخل ثوابت خاصة تصف خوارزميات التقريب: ROUND_UP- التقريب من الصفر، التقريب نحو الجزء الحقيقي:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN- التقريب إلى الصفر، أي اقتطاع الجزء الحقيقي:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_DOWN  );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN  );//-2.6
ROUND_CEILING- التقريب إلى اللانهاية الإيجابية. بمعنى، إذا كان العدد موجبًا، إذن -> ROUND_UP، وإذا كان سالبًا، ثم ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR- التقريب إلى اللانهاية السالبة، أي إذا كان العدد موجبًا، ثم -> ROUND_DOWNوإذا كان سالبًا، فعندئذ ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
بالنسبة للقيمة قيد النظر، سنعتبر هذا الرقم الأقرب بمنزلة عشرية مقطوعة بمثابة أقرب جار للرقم قيد النظر. على سبيل المثال، 2.43 سيكون أقرب إلى 2.4 من 2.5، لكن 2.48 سيكون أقرب إلى 2.5. ROUND_HALF_DOWN- التقريب إلى "أقرب جار". إذا كان كلا الجيران على مسافة متساوية من قيمة معينة، فسيتم إجراء التقريب إلى الصفر. تكون المسافة المتساوية، على سبيل المثال، عندما يكون الرقم الذي يتم تقريبه هو 5، ويكون على نفس المسافة من 0 و10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP- وضع التقريب نحو "أقرب جار". إذا كان كلا الجارين على مسافة متساوية، فسيتم التقريب لأعلى (وهذا هو نفس التقريب الذي تعلمناه في المدرسة):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.6
ROUND_HALF_EVEN- التقريب إلى "أقرب جار" إذا لم يكن كلا الجارتين على مسافة متساوية. في هذه الحالة، إذا كان الرقم الذي يتم تقريبه يسبقه رقم فردي، يتم تقريبه لأعلى، وإذا كان زوجيًا، يتم تقريبه لأسفل:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
لقد حصلنا على هذه النتيجة لأنه عند التقريب، ينظر الرقم 5 إلى الرقم السابق 2، ويرى أنه زوجي، مما يؤدي إلى التقريب للأسفل. لكن اذا:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
ويرتفع هذا التقريب، نظرًا لأن الخمسة الأخيرة تنظر إلى القيمة السابقة وترى رقمًا فرديًا. ونتيجة لذلك، يتم تقريب الرقم إلى 6، وبعد ذلك يتم تقريب الرقم 6 التالي أيضًا. لكن الرقم ستة لم يعد ينظر إلى الرقم الموجود على اليسار، حيث أن الرقم أقرب إلى الأعلى بشكل واضح، ونتيجة لذلك يتم زيادة الرقم 2 الأخير بمقدار 1. ROUND_UNNECESSARY- يستخدم للتحقق من أن الرقم لا يحتاج إلى التقريب. أي أننا نتحقق من أن الرقم يحتوي على العدد المطلوب من المنازل العشرية:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
كل شيء على ما يرام هنا، القيمة مكونة من رقمين ونتحقق من وجود رقمين فقط بعد العلامة العشرية. لكن اذا:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
ثم نحصل على - ArithmeticException، نظرًا لأن القيمة التي يتم اختبارها تتجاوز العدد المحدد من المنازل العشرية. ولكن إذا قمنا بفحص منزلتين عشريتين، ولكن في الواقع هناك واحدة، فلن يتم طرح الاستثناء، ويتم استكمال الأرقام المفقودة ببساطة بالأصفار:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
أود أيضًا أن أشير إلى أن y لها BigDecimalثوابت مشابهة للثوابت BigInteger ZEROو ONE. TENهنا رابط للوثائق . وأخيرًا: كما لاحظت على الأرجح، عند إجراء عمليات على الكائنات BigIntegerو BigDecimal، فإننا لا نغير الأشياء القديمة، بل نحصل دائمًا على أشياء جديدة. وهذا يخبرنا أنهم immutableغير قابلين للتغيير بعد خلقهم، تمامًا مثل String. بمعنى آخر، لا يمكن لجميع أساليبهم تغيير الحالة الداخلية للكائن، على الأكثر، يمكنهم إرجاع كائن جديد بالمعلمات المحددة بواسطة الوظيفة التي نستخدمها.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION