Menu
flag Ar iconالعربيةdown icon

الفئة Math في جافا: pow وsqrt وabs وround وrandom وغيرها

كيف تستخدم الفئة Math في جافا: Math.pow وMath.sqrt وMath.abs وMath.max وMath.min، والتقريب باستخدام round وfloor وceil، وتوليد أرقام عشوائية في نطاق باستخدام Math.random، والثابتان PI وE، مع نوع القيمة المُرجعة من كل دالة.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

صندوق أدوات من الدوال الساكنة

java.lang.Math فئة مليئة بدوال رياضية جاهزة: الأسس، والجذور، والقيم المطلقة، والتقريب، والدوال المثلثية، واللوغاريتمات، والأرقام العشوائية. وأمران يجعلانها سهلة الاستخدام:

  • توجد في java.lang، التي يستوردها كل ملف جافا تلقائيًا. لا حاجة إلى كتابة سطر import.
  • كل دوالها static. تستدعيها على اسم الفئة، Math.sqrt(25)، ولا تنشئ كائن Math أبدًا. تشرح صفحة الأعضاء الساكنة معنى static.

لاحظ أن بعض النتائج تُطبع مع .0 وبعضها لا. لكل دالة في Math نوع إرجاع ثابت، ومعرفته هي معظم ما يلزم تعلّمه عن هذه الفئة.

الدالةماذا تفعلتُرجع
Math.pow(a, b)a مرفوعًا إلى الأس bdouble
Math.sqrt(x)الجذر التربيعيdouble
Math.cbrt(x)الجذر التكعيبيdouble
Math.abs(x)القيمة المطلقةنوع x نفسه
Math.max(a, b) / Math.min(a, b)الأكبر / الأصغر من القيمتينالأوسع من النوعين
Math.round(x)أقرب عدد صحيحlong مع double، وint مع float
Math.floor(x) / Math.ceil(x)التقريب إلى الأسفل / إلى الأعلىdouble
Math.random()رقم عشوائي من 0.0 حتى 1.0double
Math.PI، Math.Eالثابتان π وedouble

Math.pow: الأسس

ترفع Math.pow(base, exponent) عددًا إلى أس. تأخذ معاملين من نوع double وتُرجع double، حتى عندما تمرّر أعدادًا صحيحة:

لتخزين النتيجة في int، حوّلها باستخدام (int). مع الأسس الصغيرة للأعداد الصحيحة تكون نتيجة double دقيقة، فيعطي التحويل الإجابة الصحيحة. أما النتائج الكبيرة فهي حيث يخطئ التحويل: قيمة double أكبر من Integer.MAX_VALUE (2,147,483,647) تتحول إلى Integer.MAX_VALUE بالضبط، لذا فإن (int) Math.pow(2, 40) تعطي 2147483647. حوّل إلى long مع الأسس الأكبر، وتذكّر أن double لا يستطيع تمثيل كل عدد صحيح بدقة فوق 2⁵³. تشرح صفحة تحويل الأنواع ما يفعله التحويل بالقيمة.

لا يوجد في جافا معامل للأس. 2 ^ 3 تُترجَم، لكن ^ هو XOR على مستوى البت، والنتيجة 1 وليست 8. وهذا من أكثر أخطاء المبتدئين شيوعًا في كود الرياضيات بجافا.

قيمة double التي تساوي عشرة ملايين أو أكثر تُطبع بالصيغة العلمية، وهذا يفاجئ الناس أول مرة يطبعون فيها قوة من قوى العشرة:

1.0E7 تعني 1.0 × 10⁷. القيمة نفسها لم تتغير، بل شكل الطباعة فقط. حوّل إلى long، أو نسّق باستخدام String.format("%.0f", value)، لطباعتها أرقامًا عادية.

Math.sqrt وMath.cbrt: الجذور

تُرجع Math.sqrt(x) الجذر التربيعي لـx من نوع double. وتُرجع Math.cbrt(x) الجذر التكعيبي.

الجذر التربيعي لعدد سالب ليس عددًا حقيقيًا، لذا تُرجع Math.sqrt(-4) القيمة NaN ("ليس رقمًا") بدلًا من إطلاق استثناء. وتنتشر NaN في أي عملية حسابية تمسّها، لذا تحقق من المدخلات قبل حساب الجذر إذا كانت القيم السالبة ممكنة. تحسب Math.hypot(a, b) القيمة sqrt(a*a + b*b) مباشرة، وهي طريقة شائعة لحساب المسافة بين نقطتين.

Math.abs: القيمة المطلقة

تزيل Math.abs(x) الإشارة. وعلى عكس pow وsqrt، تُرجع النوع نفسه الذي تعطيه لها: int مع int، وdouble مع double.

الاستخدام المعتاد لها هو حساب فرق يهمك حجمه لا اتجاهه، كالمسافة بين موضعين.

Math.max وMath.min

تُرجع Math.max(a, b) الأكبر من قيمتين، وMath.min(a, b) الأصغر. تأخذان وسيطين بالضبط. ولثلاث قيم أو أكثر، ضع الاستدعاءات داخل بعضها:

عندما يكون للوسيطين نوعان مختلفان، يُوسَّع النوع الأضيق أولًا. Math.max(3, 7.5) تقارن قيمتين من نوع double وتُرجع double. أما المثال الأخير فيحصر قيمة داخل النطاق من 0 إلى 100: تجعل Math.min حدها الأعلى 100، وتمنعها Math.max من النزول تحت 0.

التقريب: round وfloor وceil

في جافا ثلاث دوال للتقريب، وتختلف في الاتجاه وفي نوع الإرجاع معًا:

  • تذهب Math.round إلى أقرب عدد صحيح. والقيمة الواقعة في المنتصف تمامًا تُقرَّب إلى الأعلى، نحو اللانهاية الموجبة، فتصبح 2.5 هي 3 وتصبح -2.5 هي -2. تُرجع long مع وسيط doubleint مع float).
  • تقرّب Math.floor دائمًا إلى الأسفل، نحو اللانهاية السالبة، وتُرجع double.
  • تقرّب Math.ceil دائمًا إلى الأعلى، نحو اللانهاية الموجبة، وتُرجع double.
  • التحويل (int) ليس تقريبًا على الإطلاق: يحذف الجزء الكسري، فيُنزل الأعداد الموجبة ويرفع الأعداد السالبة.

لأن Math.round(double) تُرجع long، فإن إسنادها إلى int لا يُترجَم دون تحويل صريح:

int n = Math.round(2.6);          // خطأ في الترجمة: incompatible types: possible lossy conversion from long to int
int m = (int) Math.round(2.6);    // صحيح، m تساوي 3
long k = Math.round(2.6);         // صحيح

للتقريب إلى عدد معيّن من المنازل العشرية، كبّر القيمة، ثم قرّبها، ثم صغّرها من جديد. القسمة على 100.0 (من نوع double) بدلًا من 100 تحافظ على الكسور:

السطر الثاني يقسم long على int، وهذه قسمة صحيحة، فتضيع الكسور. وعندما تحتاج فقط إلى عرض رقم مقرّب، تكون String.format("%.2f", value) أبسط ولا تغيّر القيمة المخزنة.

Math.random: الأرقام العشوائية

تُرجع Math.random() قيمة double لا تقل عن 0.0 وأصغر من 1.0. تختلف القيمة في كل استدعاء، لذا تتغير مخرجات البرامج في هذا القسم في كل مرة تضغط فيها Run.

للحصول على عدد صحيح في نطاق، مدّد تلك القيمة، ثم حوّلها، ثم أزِحها. لعدد صحيح من min إلى max، شاملًا الطرفين:

int value = (int) (Math.random() * (max - min + 1)) + min;

وهكذا تعمل الصيغة مع النرد، حيث min تساوي 1 وmax تساوي 6:

  1. Math.random() * 6 تعطي double من 0.0 حتى 6.0 دون أن تشملها.
  2. (int) تحذف الكسر، فتعطي واحدة من 0, 1, 2, 3, 4, 5.
  3. + 1 تزيح النتيجة إلى 1, 2, 3, 4, 5, 6.

يعرض السطر الأول خمس رميات عشوائية. ويفحص السطر الثاني عشرة آلاف رمية، وعمليًا يطبع دائمًا lowest: 1, highest: 6: تصل الصيغة إلى طرفي النطاق ولا تتجاوزهما أبدًا.

الأقواس حول Math.random() * (max - min + 1) مهمة. يُطبَّق التحويل على القيمة التي تليه مباشرة، لذا فإن (int) Math.random() * 6 تحوّل Math.random() أولًا. والنتيجة دائمًا 0، و0 * 6 تساوي 0، فتخرج كل "رمية" بالقيمة نفسها.

Math.random() مناسبة للألعاب والتمارين. أما لما هو أكثر من ذلك، فالفئة java.util.Random وThreadLocalRandom.current().nextInt(min, max + 1) (في java.util.concurrent) تُرجعان أعدادًا صحيحة مباشرة، ويمكن أن تأخذ Random بذرة (seed) لتكرار السلسلة نفسها في الاختبارات. ولا شيء من هذه مناسب لكلمات المرور أو رموز الأمان، فاستخدم java.security.SecureRandom لها.

Math.PI وMath.E

Math.PI (π) وMath.E (عدد أويلر e) ثابتان من نوع static final double:

استخدمهما بدلًا من كتابة 3.14. دقتهما أقصى ما يسمح به double، والاسم يخبر القارئ ما هو الرقم.

نتائج صحيحة مقابل نتائج عشرية

تأخذ معظم دوال Math قيمًا من نوع double وتُرجع double. وعندما تعطيها قيمًا من نوع int، توسّع جافا الوسائط إلى double تلقائيًا، لكن العمليات الحسابية التي تكتبها قبل الاستدعاء تبقى تُجرى بنوع int. ومن هنا تأتي معظم الإجابات الخاطئة:

items / perBox هي 7 / 2، وقسمة قيمتين من نوع int تتخلص من الباقي، فتكون النتيجة 3 قبل أن تراها Math.ceil أصلًا. وMath.ceil(3.0) تساوي 3.0. اجعل أحد الطرفين double، بتحويل صريح أو بقيمة حرفية مثل 4.0، حتى تحتفظ القسمة بكسرها. تشرح صفحة المعاملات القسمة الصحيحة بتفصيل أكبر.

القاعدة العامة: حدّد النوع الذي تريده في النهاية، واجعل القسمة أو الضرب يُجرى بنوع double عندما تهمك الكسور، ولا تحوّل إلى int أو long إلا مرة واحدة في النهاية.

دوال مفيدة أخرى

بعض الدوال الأخرى من الفئة نفسها، وكلها تُستدعى بالطريقة نفسها:

  • Math.log هي اللوغاريتم الطبيعي، وMath.log10 للأساس 10.
  • تعطي Math.floorMod(a, b) باقيًا بإشارة b، وهذا ما تحتاجه للدوران داخل نطاق مثل أيام الأسبوع. أما المعامل % فيحتفظ بإشارة a.
  • تأخذ الدوال المثلثية (sin وcos وtan) الزوايا بالراديان. حوّل الدرجات أولًا باستخدام Math.toRadians.
  • تطلق Math.addExact وMath.multiplyExact وأخواتها استثناء ArithmeticException عند الفيض (overflow) بدلًا من الالتفاف بصمت إلى عدد سالب.

الأسئلة الشائعة

كيف أستخدم Math.pow في جافا؟

تُرجع Math.pow(base, exponent) قيمة base مرفوعة إلى الأس exponent من نوع double، لذا فإن Math.pow(2, 3) تساوي 8.0. ولتخزين النتيجة في int حوّلها: int n = (int) Math.pow(2, 10); تعطي 1024. لا يوجد في جافا معامل أس ^، فـ^ هو XOR على مستوى البت.

كيف أولّد رقمًا عشوائيًا في نطاق باستخدام Math.random؟

تُرجع Math.random() قيمة double من 0.0 حتى 1.0 دون أن تشملها. للحصول على عدد صحيح من min إلى max شاملًا الطرفين، استخدم (int) (Math.random() * (max - min + 1)) + min. ورمية النرد هي (int) (Math.random() * 6) + 1.

هل أحتاج إلى استيراد الفئة Math في جافا؟

لا. Math موجودة في الحزمة java.lang، التي يستوردها كل ملف جافا تلقائيًا. وكل دوالها static، لذا تستدعيها على اسم الفئة، كما في Math.sqrt(16)، دون إنشاء كائن.

لماذا تُرجع Math.round قيمة long في جافا؟

تُرجع Math.round(double) قيمة long لأن double يمكنه حمل قيم أكبر بكثير من نطاق int. وإسناد النتيجة إلى int يحتاج إلى تحويل صريح: int n = (int) Math.round(2.6);. أما Math.round(float) فتُرجع int.

ما الفرق بين Math.floor وMath.ceil وMath.round؟

تقرّب Math.floor إلى الأسفل (2.7 تصبح 2.0، و-2.3 تصبح -3.0)، وتقرّب Math.ceil إلى الأعلى (2.1 تصبح 3.0)، وتذهب Math.round إلى أقرب عدد صحيح، مع تقريب النصف إلى الأعلى (2.5 تصبح 3). تُرجع floor وceil قيمة double، وتُرجع round قيمة long.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن