كائن `Math`

تشرح هذه المقالة كائن Math۔

يشرح خطوة بخطوة، من الاستخدام الأساسي إلى الأنماط العملية الشائعة، بالإضافة إلى المصاعب والإجراءات الوقائية۔

YouTube Video

كائن Math

يوفر كائن Math في جافاسكريبت مجموعة من الأدوات المدمجة للحسابات العددية۔

الثوابت

الثوابت المعرفة في Math مفيدة عند التعامل مع القيم عالية الدقة۔

الكود التالي يوضح بعض الثوابت النموذجية۔

1// Show common Math constants
2console.log("Math.PI:", Math.PI);         // 3.141592653589793
3console.log("Math.E:", Math.E);           // Euler's number
4console.log("Math.LN2:", Math.LN2);       // Natural log of 2
5console.log("Math.SQRT2:", Math.SQRT2);   // Square root of 2
  • يمكن استخدام هذه الثوابت كما هي في الدوال المثلثية، التحويلات اللوغاريتمية، التطبيع، وأكثر۔ على سبيل المثال، نحتاج إلى Math.PI لتحويل الزوايا إلى راديان۔

التقريب الأساسي والقيم المطلقة (abs، floor، ceil، round، trunc)

التقريب ومعالجة الإشارات تُستخدم كثيراً، لذلك من المهم فهم الفروقات بين Math.floor و Math.ceil و Math.round جيداً۔ خاصة عند التعامل مع الأرقام السالبة، قد تختلف النتائج عن الحدس، لذلك يجب الانتباه إلى كيفية عمل كل قاعدة تقريب واستخدامها بشكل مناسب۔

الأمثلة التالية توضح الفروقات بين دوال التقريب۔

 1// Examples of rounding and absolute value functions
 2const pos = 3.7;
 3const neg = -3.7;
 4
 5// --- floor ---
 6console.log("Math.floor(3.7):", Math.floor(pos));  // 3
 7console.log("Math.floor(-3.7):", Math.floor(neg)); // -4
 8// (rounds toward smaller value)
 9
10// --- ceil ---
11console.log("Math.ceil(3.7):", Math.ceil(pos));  // 4
12console.log("Math.ceil(-3.7):", Math.ceil(neg)); // -3
13// (rounds toward larger value)
14
15// --- round ---
16console.log("Math.round(3.5):", Math.round(3.5));   // 4
17// (.5 goes up for positive numbers)
18console.log("Math.round(-3.5):", Math.round(-3.5)); // -3
19// (.5 moves toward zero for negative numbers)
20
21// --- trunc ---
22console.log("Math.trunc(3.7):", Math.trunc(pos));  // 3
23console.log("Math.trunc(-3.7):", Math.trunc(neg)); // -3
24// (fraction removed toward zero)
25
26// --- abs ---
27console.log("Math.abs(-3.7):", Math.abs(neg)); // 3.7
  • Math.floor يقوم بالتقريب نحو الرقم الأصغر للأعداد السالبة، لذلك يصبح -3.7 هو -4۔
  • Math.ceil يقوم بالتقريب نحو الرقم الأكبر للأعداد السالبة، لذلك يصبح -3.7 هو -3۔
  • Math.round يقرب 0.5 للأعلى للأرقام الموجبة، وللأرقام السالبة يقرب باتجاه الصفر۔
  • الأرقام السالبة قد تعطي نتائج تختلف عما تتوقعه، لذلك من المهم فهم اتجاه التقريب بدقة۔
  • يجب اختيار دوال التقريب حسب حالة الاستخدام۔ على سبيل المثال، استخدم Math.floor لحساب الفهارس، وMath.ceil للحدود العليا، وMath.trunc عند حذف الجزء العشري فقط۔

الضرب، والأسس، والجذور (pow، **، sqrt، cbrt، hypot)

يمكن إجراء الأسس والجذور التربيعية باستخدام Math.pow أو عامل **۔ Math.hypot يحسب الجذر التربيعي لمجموع المربعات (المسافة) بشكل آمن۔

فيما يلي أمثلة على رفع للأس وقيمة الدالة hypot۔ Math.hypot يقلل من خطر تجاوز الحدود العددية أو نقصانها۔

1// Power, root and hypot examples
2console.log("2 ** 10:", 2 ** 10);                // 1024
3console.log("Math.pow(2, 10):", Math.pow(2, 10));// 1024
4console.log("Math.sqrt(16):", Math.sqrt(16));    // 4
5console.log("Math.cbrt(27):", Math.cbrt(27));    // 3
6console.log("Math.hypot(3, 4):", Math.hypot(3, 4));// 5 (3-4-5 triangle)
  • Math.hypot مفيد عند التعامل مع أطوال أضلاع مثلث أو أطوال المتجهات متعددة الأبعاد۔

الدوال الأسية واللوغاريتمية (exp، log، log10، log2)

الأسس واللوغاريتمات تُستخدم كثيراً في الاحتمالات، والانحلال الأسي، والموازنة۔

فيما يلي أمثلة أساسية على exp واللوغاريتمات۔ تأكد من استخدام الدالة المناسبة حسب قاعدة اللوغاريتم۔

1// Exponential and logarithm examples
2console.log("Math.exp(1):", Math.exp(1));     // e^1
3console.log("Math.log(Math.E):", Math.log(Math.E)); // natural log, 1
4console.log("Math.log10(100):", Math.log10(100));   // 2
5console.log("Math.log2(8):", Math.log2(8));         // 3
  • اللوغاريتمات الطبيعية (Math.log) معيارية في الإحصاء والمعادلات التفاضلية۔ كما تحدد اللوغاريتمات العشرية أو الثنائية حسب التطبيق المستخدم۔

الدوال المثلثية (sin، cos، tan، asin، acos، atan2)

الدوال المثلثية ضرورية لحساب الزوايا، والدوران، وتحويل الإحداثيات۔ الدالة Math.atan2(y, x) مفيدة لحساب الزوايا مع مراعاة الربع الصحيح۔

فيما يلي أمثلة أساسية واستخدامات الدالة atan2۔ يجب التعامل مع الزوايا بوحدة الراديان۔

 1// Trigonometry examples (angles in radians)
 2const degToRad = deg => deg * (Math.PI / 180);
 3const radToDeg = rad => rad * (180 / Math.PI);
 4
 5console.log("Math.sin(PI/2):", Math.sin(Math.PI / 2));          // 1
 6console.log("Math.cos(0):", Math.cos(0));                      // 1
 7console.log("Math.tan(Math.PI / 4):", Math.tan(Math.PI / 4));  // ~1
 8
 9// Using atan2 to compute angle of vector (x, y)
10const x = -1, y = 1;
11const angle = Math.atan2(y, x); // returns angle in radians taking quadrant into account
12console.log("atan2(1, -1) in degrees:", radToDeg(angle));      // 135
  • تستطيع atan2 تحديد زاوية المتجه بأمان، وهذا يجعلها مفضلة في حسابات الدوران والاتجاه۔

توليد الأرقام العشوائية (Math.random وأنماط عملية)

ترجع Math.random() عدداً عشوائياً موزعاً بالتساوي ضمن النطاق [0، 1)۔ يمكنك تحويله أو توسيعه للنطاقات الصحيحة أو التوزيعات الطبيعية حسب الحاجة۔

الأمثلة التالية توضح دوال مساعدة لتوليد الأرقام العشوائية۔ إذا احتجت أرقاماً عشوائية آمنة تشفيرياً، استخدم crypto.getRandomValues۔

 1// Random utilities using Math.random
 2
 3// Get integer in [min, max] inclusive
 4function randomInt(min, max) {
 5  // Returns integer between min and max (inclusive)
 6  return Math.floor(Math.random() * (max - min + 1)) + min;
 7}
 8console.log("randomInt(1, 6):", randomInt(1, 6)); // dice roll example
 9
10// Get float in [min, max)
11function randomFloat(min, max) {
12  return Math.random() * (max - min) + min;
13}
14console.log("randomFloat(0, 5):", randomFloat(0, 5));
15
16// Fisher-Yates shuffle
17function shuffle(array) {
18  for (let i = array.length - 1; i > 0; i--) {
19    const j = Math.floor(Math.random() * (i + 1));
20    // swap array[i] and array[j]
21    [array[i], array[j]] = [array[j], array[i]];
22  }
23  return array;
24}
25console.log("shuffle([1,2,3,4,5]):", shuffle([1,2,3,4,5]));
  • Math.random مفيد للاستخدام العام، لكن في ألعاب الإعادة أو التشفير يتطلب الأمر إجراءات لإعادة الإنتاج أو الأمان۔

مساعدات عملية (clamp، lerp، mapRange، تطبيع الزوايا)

من المفيد كتابة دوال مساعدة صغيرة بنفسك للمهام الرياضية الشائعة الاستخدام۔

فيما يلي أمثلة تسهل تنفيذ أدوات مستخدمة بشكل متكرر۔

 1// Utility functions: clamp, lerp, mapRange, normalizeAngle
 2
 3// Clamp value between min and max
 4function clamp(v, min, max) {
 5  return Math.max(min, Math.min(max, v));
 6}
 7console.log("clamp(10, 0, 5):", clamp(10, 0, 5)); // 5
 8
 9// Linear interpolation: t in [0,1]
10function lerp(a, b, t) {
11  return a + (b - a) * t;
12}
13console.log("lerp(0, 10, 0.25):", lerp(0, 10, 0.25)); // 2.5
14
15// Map value from one range to another
16function mapRange(v, inMin, inMax, outMin, outMax) {
17  const t = (v - inMin) / (inMax - inMin);
18  return lerp(outMin, outMax, t);
19}
20console.log("mapRange(5, 0, 10, 0, 100):", mapRange(5, 0, 10, 0, 100));
21// -> 50
22
23// Normalize angle to [-PI, PI)
24function normalizeAngle(rad) {
25  return Math.atan2(Math.sin(rad), Math.cos(rad));
26}
27console.log("normalizeAngle(3*PI):", normalizeAngle(3 * Math.PI));
  • هذا الكود يجمع دوال مساعدة صغيرة شائعة للاستخدام في العمليات العددية مثل تثبيت القيم، والاستيفاء، وتحويل النطاقات، وتطبيع الزوايا۔ clamp يحدد القيمة ضمن نطاق معين، بينما lerp و mapRange ينفذان استيفاءً سلساً أو تحويل النطاق۔ بالإضافة إلى ذلك، تقوم دالة normalizeAngle دائماً بتطبيع الزوايا إلى النطاق [-π، π) لتثبيت حسابات الدوران۔
  • تستخدم هذه الدوال المساعدة بكثرة في الرسوميات والألعاب وبرمجة التفاعل۔ normalizeAngle مهمة لمقارنة الفروقات الزاوية وللاستيفاء۔

ملاحظات حول الكسور العشرية والتقريب (الدقة والمقارنة)

الأرقام في جافاسكريبت من نوع الكسور العشرية مزدوجة الدقة (IEEE-754 بواقع 64 بت)، لذا يلزم الحذر عند المقارنة أو التقريب۔ على سبيل المثال، 0.1 + 0.2 !== 0.3۔

فيما يلي مثال على معالجة أخطاء التقريب۔ من المهم استخدام مقارنات تتحمل الأخطاء الصغيرة أو دوال تقريب مناسبة۔

1// Floating point precision example and safe equality
2console.log("0.1 + 0.2 === 0.3 :", 0.1 + 0.2 === 0.3); // false
3
4function nearlyEqual(a, b, eps = 1e-12) {
5  return Math.abs(a - b) <= eps;
6}
7console.log("nearlyEqual(0.1+0.2, 0.3):", nearlyEqual(0.1 + 0.2, 0.3));
8// -> true
  • لتحقق قوي من تساوي الأرقام استخدم خطأ القيمة المطلقة (eps) أو الخطأ النسبي۔

نصائح الأداء

دوال Math محسّنة بشكل أصلي وعادةً تكون أسرع من كتابة منطق مكافئ يدوياً۔ إذا تم تكرار نفس العملية الحسابية (مثل Math.PI / 180) داخل حلقة، فمن الأفضل تعيينها لمتغير مسبقاً لتقليل الحمل الزائد۔

فيما يلي مثال لتحويل الدرجات إلى راديان عن طريق إنشاء ثابت خارج الحلقة۔

1// Cache conversion factor for performance
2const DEG_TO_RAD = Math.PI / 180;
3const RAD_TO_DEG = 180 / Math.PI;
4
5for (let deg = 0; deg < 360; deg += 10) {
6  // Use cached constant instead of computing each time
7  const rad = deg * DEG_TO_RAD;
8  // ... do work with rad
9}
  • من الأفضل التحقق من المواقع الساخنة فعلياً باستخدام أداة قياس الأداء قبل البدء في التحسينات۔
  • من الفعّال تخزين الثوابت المستخدمة كثيراً۔

التوافق والتعويضات البرمجية (polyfills)

كائن Math موجود منذ زمن طويل، لكن بعض الدوال مثل Math.cbrt و Math.log10 و Math.log2 و Math.hypot قد لا تكون مدعومة في البيئات الأقدم۔ جهز تعويض برمجي بسيط إذا لزم الأمر۔

فيما يلي مثال على تعويض برمجي بسيط لدالة Math.log2۔

1// Polyfill for Math.log2 if needed
2if (!Math.log2) {
3  Math.log2 = function(x) {
4    return Math.log(x) / Math.LN2;
5  };
6}
7console.log("Math.log2(8):", Math.log2(8));

الكثير من البيئات تدعمها بالفعل، ولكن تحقق من التوافق إذا كان ذلك مطلوباً۔

تحقق من دعم المتصفحات وفقاً للبيئة المستهدفة في مشروعك۔

مثال عملي: التحديث بخطوات زمنية في محاكاة فيزيائية بسيطة

أخيراً، إليك مثال عملي يجمع عدة دوال من Math۔ هذا مثال بسيط جداً لتحديث الموضع، والسرعة، والتحكم في الزاوية۔

إنه نموذج مبسط جدًا لمحرك فيزيائي۔

 1// Clamp value between min and max
 2function clamp(v, min, max) {
 3  return Math.max(min, Math.min(max, v));
 4}
 5
 6// Normalize angle to [-PI, PI)
 7function normalizeAngle(rad) {
 8  return Math.atan2(Math.sin(rad), Math.cos(rad));
 9}
10
11// Simple physics step example using Math utilities
12function step(state, dt) {
13  // state: { x, y, vx, vy, angle, angularVelocity }
14  // dt: time delta in seconds
15  // Integrate linear motion
16  state.x += state.vx * dt;
17  state.y += state.vy * dt;
18
19  // Integrate angular motion and normalize angle
20  state.angle = normalizeAngle(state.angle + state.angularVelocity * dt);
21
22  // Keep position within bounds [0, width] x [0, height]
23  state.x = clamp(state.x, 0, state.width);
24  state.y = clamp(state.y, 0, state.height);
25  return state;
26}
27
28const state = { x: 10, y: 10, vx: 2, vy: 0.5, angle: 0, angularVelocity: 0.1, width: 100, height: 100 };
29console.log("before:", state);
30step(state, 0.016); // simulate ~1 frame at 60fps
31console.log("after:", state);
  • من خلال دمج مساعدين مثل Math، يمكن جعل منطق المحاكاة والتحريك أكثر اختصاراً۔

الملخص

  • Math يغطي كل شيء بدءًا من الثوابت والدوال الأساسية وحتى المتقدمة، ويعتبر أساس المعالجة العددية۔
  • اختر الدوال حسب الغرض، سواءً للأرقام العشوائية، أو الدوال المثلثية، أو الدوال الأسية/اللوغاريتمية، أو التقريب؛ واصنع دوال مساعدة صغيرة مثل clamp و lerp للاستخدام العملي۔
  • انتبه لدقة الأرقام العشرية وحالة دعم البيئة المستهدفة، وحضّر تحمّل الأخطاء أو التعويضات البرمجية عند الحاجة۔

يمكنك متابعة المقالة أعلاه باستخدام Visual Studio Code على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔

YouTube Video