JavaRush /مدونة جافا /Random-AR /عامل في برمجة جافا

عامل في برمجة جافا

نشرت في المجموعة
اليوم سنتحدث عن العوامل. هذه واحدة من أهم الوظائف الأساسية التي يحتاج المبرمج إلى معرفتها، وفي نفس الوقت يكون قادرًا على التعامل معها. اذا هيا بنا نبدأ. مضروب n هو قيمة منتج (ضرب) جميع الأعداد الطبيعية من 1 إلى n، والتي يُشار إليها بالرمز n! ما يبدو عليه:
1! =  1
2! =  1 * 2 = 2
3! =  1 * 2 * 3 = 6
4! =  1 * 2 * 3 * 4 = 24
5! =  1 * 2 * 3 * 4 * 5  = 120
وقاعدة صغيرة أخرى، لـ 0:
!0  = 1
فإذا أردنا مثلاً الحصول على فرق مضروب 6! و 4!:
6!-4! = 1⋅2⋅3⋅4⋅5⋅6 - 1⋅2⋅3⋅4 = 720 - 24 = 696
دعونا نلقي نظرة على الشكل الذي سيبدو عليه هذا في Java ونفهم عدة طرق يمكن من خلالها حساب المضروب.

الحل المعتاد

public static int getFactorial(int f) {
  int result = 1;
  for (int i = 1; i <= f; i++) {
     result = result * i;
  }
  return result;
}
لا شيء معقد: نستخدم الرقم المستلم كحجم دورتنا، التي نضرب فيها جميع الأرقام السابقة حتى نصل إلى f. وفي الرئيسي:

System.out.println(getFactorial(6) - getFactorial(4));
نتحقق ونحصل على النتيجة المرجوة: 696.

الحل العودي

العودية هي القيام ببعض المنطق عن طريق استدعاء أسلوب على نفسه. هذه الطريقة تسمى العودية. عادة يتكون من جزأين:
  1. حالة خروج الطريقة، عند الوصول إليها يجب أن تتوقف الطريقة عن استدعاء نفسها وتبدأ في تمرير القيم لأعلى. وإلا، فسنحصل على حلقة لا نهائية من استدعاء أسلوب على نفسه، ونتيجة لذلك، StackOverflowError .

  2. بعض المعالجة (المنطق) ضرورية في موقف معين + استدعاء نفسها، ولكن بقيمة واردة مختلفة.

مثالنا المثالي للتكرار اليوم هو إيجاد المضروب:
public static int getFactorial(int f) {
  if (f <= 1) {
     return 1;
  }
  else {
     return f * getFactorial(f - 1);
  }
}
قمنا بتعيين شرط الخروج من العودية عندما يصل إلى 1. إذا لم تكن الوسيطة 1، فإننا نضرب القيمة الحالية بنتيجة الاستدعاء التالي لهذه الطريقة (حيث نرسل القيمة الحالية -1).

الحل مع ستريم

بالنسبة لأولئك الذين لا يعرفون وظيفة الدفق أو لأولئك الذين يرغبون في تحديث ذاكرتهم، سيكون من المفيد قراءة هذا .
public static int getFactorial(int f) {
  if (f <= 1) {
     return 1;
  }
  else {
     return IntStream.rangeClosed(2, f).reduce((x, y) -> x * y).getAsInt();
  }
}
نستخدم هنا فئة خاصة من IntStream، والتي توفر إمكانيات إضافية عند العمل مع الدفق من قيم int. لإنشاء مثل هذا الدفق، نستخدم أسلوبه الثابت rangeClosed، الذي ينشئ قيمًا من 2 إلى f شاملة بخطوة 1. بعد ذلك، نقوم بدمج جميع القيم باستخدام طريقة التخفيض، أي نوضح فيه كيف نريد الجمع بينهما. وأخيرًا، نحصل على القيمة الناتجة باستخدام طريقة getAsInt الطرفية.

باستخدام BigInteger

في Java، غالبًا ما يتم استخدام فئة BigInteger للتعامل مع الأرقام، خاصة الكبيرة منها . بعد كل شيء، إذا استخدمنا int، فإن الحد الأقصى للمضروب الذي يمكننا أخذه دون فقدان البيانات هو 31، لفترة طويلة - 39. ولكن ماذا لو كنا بحاجة إلى مضروب 100؟ دعونا ننظر إلى الحلول السابقة، ولكن باستخدام BigInteger. العامل في برمجة جافا - 2

الحل المعتاد

public static BigInteger getFactorial(int f) {
  BigInteger result = BigInteger.ONE;
  for (int i = 1; i <= f; i++)
     result = result.multiply(BigInteger.valueOf(i));
  return result;
}
خوارزمية العد هي نفسها بشكل أساسي، ولكننا هنا نستخدم إمكانيات BigInteger: BigInteger.ONE - لتعيين قيمة البداية على 1. ضرب - الضرب بين قيمة العامل السابقة والرقم الحالي.

الحل العودي

public static BigInteger getFactorial(int f) {
  if (f <= 1) {
     return BigInteger.valueOf(1);
  }
  else {
     return BigInteger.valueOf(f).multiply(getFactorial(f - 1));
  }
}
لا يتغير المنطق العام للحل، باستثناء إضافة بعض طرق العمل مع BigInteger.

الحل مع ستريم

public static BigInteger getFactorial(int f) {
  if (f < 2) {
     return BigInteger.valueOf(1);
  }
  else {
     return IntStream.rangeClosed(2, f).mapToObj(BigInteger::valueOf).reduce(BigInteger::multiply).get();
  }
}
في الأساس، كل شيء هو نفسه، ولكن مع BigInteger. في الدفق، لدينا الآن طريقة MapToObj، والتي من خلالها نقوم بتحويل قيم int إلى BigInteger من أجل ضربها معًا لاحقًا باستخدام الضرب (حسنًا، أضفنا الحصول على كائن من الغلاف الاختياري ). إذا قمنا بتشغيل أي من هذه الطرق الثلاث باستخدام الوسيطة 100، فلن يكون لدينا تجاوز السعة وسنحصل على:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION