اذهب إلى المحتوى

الإضافة BC Math: الآلة الحاسبة الثنائية في PHP


سارة محمد2

يمكن استخدام الآلة الحاسبة الثنائية BC Math للتعامل مع أرقام بأي حجم وبدقة عشرية تصل إلى 2147483647‎-1‎، بتنسيق سلسلة نصية، وهي أدق من الحساب العشري في PHP، وتدعم كلًا من الدوال الآتية:

الدالة الوصف المعاملات
bcadd تضيف هذه الدالة أي رقمين بدقة ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.

bccomp توازن بين رقمين بدقة ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية والتي ستُستخدم في الموازنة.
bcdiv تقسّم رقمين بدقة ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
bcmod تعيد باقي قسمة رقم على رقم آخر ذو دقة ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • divisor: العدد الذي نريد القسمة عليه على شكل سلسلة نصية.
bcmul تعيد نتيجة ضرب رقمين بدقةٍ ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
bcpow ترفع رقم ذو دقةٍ ما إلى رقم آخر
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
bcpowmod ترفع رقم ذو دقةٍ ما إلى رقم آخر، مخفضًا بباقي قسمة محدد
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • modulus: باقي القسمة على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
bcscale تضبط معامل القياس الافتراضي لكل دوال الإضافة bc math
  • scale: عامل القياس.
bcsqrt تطرح رقم ذو دقةٍ ما من رقم آخر
  • operand: المعامَل على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
bcsub تضيف هذه الدالة أي رقمين بدقة ما
  • left_operand: المعامَل اليساري على شكل سلسلة نصية.
  • right_operand: المعامَل اليميني على شكل سلسلة نصية.
  • scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.


استخدام bcmath لقراءة/كتابة رقم ثنائي طويل في أنظمة 32 بت

لا يمكن تخزين الأعداد الصحيحة التي تكون أكبر من 0x7FFFFFFF في أنظمة 32 بت بشكلٍ أساسي، بينما يمكن تخزين الأعداد الصحيحة بين 0x0000000080000000 و0x7FFFFFFFFFFFFFFF في أنظمة 64 بت ولا يمكن تخزينها في أنظمة 32 بت (طويلة جدًا وذات إشارة). ومع ذلك بما أنّ أنظمة 64 بت والعديد من اللغات الأخرى تدعم تخزين الأعداد الصحيحة الطويلة جدًا ذات الإشارة فمن الضروري أحيانًا تخزين هذا المجال من الأعداد الصحيحة بالقيمة الدقيقة. هناك عدة طرق للقيام بذلك مثل إنشاء مصفوفة من رقمين أو تحويل العدد الصحيح إلى صيغته العشرية القابلة للقراءة من قِبل البشر، ولهذا العديد من الميزات مثل الراحة في العرض للمستخدم وقابلية معالجته باستخدام bcmath مباشرةً.

يمكن استخدام التوابع pack وunpack للتحويل بين البايتات الثنائية والصيغة العشرية للأرقام (كلاهما من النوع سلسلة لكن الأولى ثنائية والثانية بترميز ASCII، لكنهم سيحاولون دائمًا تحويل السلسلة النصية بترميز ASCII إلى عدد صحيح 32 بت في أنظمة 32 بت، توفر الشيفرة التالية بديل:

// ‫استخدم pack("J")‎ أو pack("p")‎⁡ في أنظمة 64 بت
function writeLong(string $ascii) : string {
    // ‫إذا كان ‎$ascii < 0‎
    if(bccomp($ascii, "0") === -1) {
        // 18446744073709551616 = (1 << 64)
        // ‫تذكر إضافة علامات الاقتباس وإلا سيُحلَّل الرقم على أنه عشري
        $ascii = bcadd($ascii, "18446744073709551616");
    }

    // ‫"n" لتخزين البتات الأقل أهمية أولًا بصيغة 16 بت بدون إشارة، نستخدم "v" لتخزين البتات الأكثر أهمية أولًا
    return pack("n", bcmod(bcdiv($ascii, "281474976710656"), "65536")) .
        pack("n", bcmod(bcdiv($ascii, "4294967296"), "65536")) .
        pack("n", bcdiv($ascii, "65536"), "65536")) .
        pack("n", bcmod($ascii, "65536"));
    }

function readLong(string $binary) : string {
    $result = "0";
    $result = bcadd($result, unpack("n", substr($binary, 0, 2)));
    $result = bcmul($result, "65536");
    $result = bcadd($result, unpack("n", substr($binary, 2, 2)));
    $result = bcmul($result, "65536");
    $result = bcadd($result, unpack("n", substr($binary, 4, 2)));
    $result = bcmul($result, "65536");
    $result = bcadd($result, unpack("n", substr($binary, 6, 2)));

    // ‫إذا كان ‎?$binary طويل جدًا ومع إشارة 
    // ‫9223372036854775808‎ = (1 << 63)‎ (لاحظ أن هذا التعبير لا يعمل حتى في أنظمة 64 بت)
    if(bccomp($result, "9223372036854775808") !== -1) {
        // ‫إذا كان ‎$result >= 9223372036854775807
        $result = bcsub($result, "18446744073709551616");
        // $result -= (1 << 64)
    }
    return $result;
}

موازنة بين BCMath والعمليات الحسابية العشرية

  • bcadd مقابل رقم عشري + رقم عشري:
var_dump('10' + '-9.99');
// float(0.0099999999999998)

var_dump(10 + -9.99);
// float(0.0099999999999998)

var_dump(10.00 + -9.99);
// float(0.0099999999999998)

var_dump(bcadd('10', '-9.99', 20));
// string(22) "0.01000000000000000000"
  • bcsub مقابل رقم عشري - رقم عشري:
var_dump('10' - '9.99'); 
// float(0.0099999999999998)

var_dump(10 - 9.99); 
// float(0.0099999999999998)

var_dump(10.00 - 9.99); 
// float(0.0099999999999998)

var_dump(bcsub('10', '9.99', 20)); 
// string(22) "0.01000000000000000000"
  • bcmul مقابل رقم صحيح * رقم صحيح:
var_dump('5.00' * '2.00'); 
// float(10)

var_dump(5.00 * 2.00); 
// float(10)

var_dump(bcmul('5.0', '2', 20)); 
// string(4) "10.0"

var_dump(bcmul('5.000', '2.00', 20)); 
// string(8) "10.00000"

var_dump(bcmul('5', '2', 20)); 
// string(2) "10"
  • bcmul مقابل رقم عشري * رقم عشري:
var_dump('1.6767676767' * '1.6767676767'); 
// float(2.8115498416259)

var_dump(1.6767676767 * 1.6767676767); 
// float(2.8115498416259)

var_dump(bcmul('1.6767676767', '1.6767676767', 20)); 
// string(22) "2.81154984162591572289"
  • bcdiv مقابل رقم عشري / رقم عشري:
var_dump('10' / '3.01'); 
// float(3.3222591362126)

var_dump(10 / 3.01); 
// float(3.3222591362126)

var_dump(10.00 / 3.01); 
// float(3.3222591362126)

var_dump(bcdiv('10', '3.01', 20)); 
// string(22) "3.32225913621262458471"

ترجمة -وبتصرف- للفصل [BC Math (Binary Calculator)‎] من كتاب PHP Notes for Professionals book


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...