يمكن استخدام الآلة الحاسبة الثنائية BC Math للتعامل مع أرقام بأي حجم وبدقة عشرية تصل إلى 2147483647-1، بتنسيق سلسلة نصية، وهي أدق من الحساب العشري في PHP، وتدعم كلًا من الدوال الآتية:
الدالة | الوصف | المعاملات |
---|---|---|
bcadd | تضيف هذه الدالة أي رقمين بدقة ما |
|
bccomp | توازن بين رقمين بدقة ما |
|
bcdiv | تقسّم رقمين بدقة ما |
|
bcmod | تعيد باقي قسمة رقم على رقم آخر ذو دقة ما |
|
bcmul | تعيد نتيجة ضرب رقمين بدقةٍ ما |
|
bcpow | ترفع رقم ذو دقةٍ ما إلى رقم آخر |
|
bcpowmod | ترفع رقم ذو دقةٍ ما إلى رقم آخر، مخفضًا بباقي قسمة محدد |
|
bcscale | تضبط معامل القياس الافتراضي لكل دوال الإضافة bc math |
|
bcsqrt | تطرح رقم ذو دقةٍ ما من رقم آخر |
|
bcsub | تضيف هذه الدالة أي رقمين بدقة ما |
|
استخدام 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
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.