حساب القيمة المطلقة لعدد صحيح دون استخدام التفريع
القيمة المطلقة لعدد معين هي القيمة غير السالبة لذلك العدد دون النظر إلى إشارته، ويرمز لها بالرمز |x|
.
لا حاجة لحساب القيمة المطلقة للعدد الموجب لأنّها تكون مساوية له، وإن كان العدد المعطى سالبًا فسنحتاج فقط إلى قلب إشارته، ولمّا كانت الأعداد السالبة تخزّن بهيئة متمم الاثنين 2’s complement، فإن الحصول على القيمة المطلقة للعدد السالب تتطلب تغيير حالة العبتات في العدد ثم إضافة 1
إلى الناتج.
فعلى سبيل المثال يخزّن العدد -2
في النظام ثماني البتات بالصيغة 1 1 1 1 1 1 1 0
، ويمثّل البت في أقصى يسار العدد بت الإشارة. وللحصول على القيمة المطلقة للعدد السالب، يجب تبديل جميع البتات ثم إضافة 1
إلى العدد الناتج، أي 0 0 0 0 0 0 0 1 + 1
سيعطي الناتج 1 1 1 1 1 1 1 0
.
الطريقة الأولى
تتبع الطريقة الأولى الخطوات التالية:
1- سيحمل المتغير mask
ناتج الإزاحة اليمينة للعدد الصحيح بمقدار 31
(على فرض أنّ العدد الصحيح مخزّن باستخدام 32 بت).
mask = n >> 31
2- ينتج عن الخطوة السابقة المقدار 1 1 1 1 1 1 1 1
للأعداد السالبة والمقدار 0 0 0 0 0 0 0 0
للأعداد الموجبة. تُضاف قيمة المتغير إلى العدد المعطى.
mask + n
3- يؤدي تطبيق العامل XOR
على القيمتين السابقتين mask + n
و mask
إلى الحصول على القيمة المطلقة للعدد المعطى.
تنفيذ الطريقة
تعرض الأمثلة التالية كيفية تنفيذ هذه الطريقة في عدد من لغات البرمجة:
- C++:
#include <bits/stdc++.h>
using namespace std;
#define CHARBIT 8
unsigned int getAbs(int n)
{
int const mask = n >> (sizeof(int) * CHARBIT - 1);
return ((n + mask) ^ mask);
}
/* اختبار الدالة السابقة */
int main()
{
int n = -6;
cout << "Absoute value of " << n << " is " << getAbs(n);
return 0;
}
- بايثون:
CHARBIT = 8
SIZE_INT = 8
def getAbs(n):
mask = n >> (SIZE_INT * CHARBIT - 1)
return ((n + mask) ^ mask)
# اختبار الدالة السابقة
n = -6
print("Absolute value of",n,"is",getAbs(n))
- جافا:
class GFG {
static final int CHAR_BIT = 8;
static final int SIZE_INT = 8;
static int getAbs(int n)
{
int mask = n >> (SIZE_INT * CHAR_BIT - 1);
return ((n + mask) ^ mask);
}
/* اختبار الدالة السابقة */
public static void main(String[] args)
{
int n = -6;
System.out.print("Absoute value of " + n + " is " + getAbs(n));
}
}
تعطي الشيفرات السابقة المخرجات التالية:
Absolute value of -6 is 6
الطريقة الثانية
تتبع الطريقة الأولى الخطوات التالية:
1- سيحمل المتغير mask
ناتج الإزاحة اليمينة للعدد الصحيح بمقدار 31
(على فرض أنّ العدد الصحيح مخزّن باستخدام 32 بت).
mask = n >> 31
2- تطبيق العامل XOR
على العدد الناتج من الخطوة السابقة والعدد المعطى.
mask ^ n
3- طريقة قيمة المتغير mask
من نتيجة الخطوة الثانية وإعادة الناتج.
(mask^n) - mask
تنفيذ الطريقة
تعرض الأمثلة التالية كيفية تنفيذه هذه الطريقة في عدد من لغات البرمجة:
- C++:
/* This function will return absolute value of n*/
unsigned int getAbs(int n)
{
int const mask = n >> (sizeof(int) * CHAR_BIT - 1);
return ((n ^ mask) - mask);
}
/* اختبار الدالة السابقة */
int main()
{
int n = -6;
cout << "Absoute value of " << n << " is " << getAbs(n);
return 0;
}
- بايثون:
CHARBIT = 8
SIZE_INT = 8
def getAbs(n):
mask = n >> (SIZE_INT * CHARBIT - 1)
return ((n ^ mask) - mask)
# اختبار الدالة السابقة
n = -6
print("Absolute value of",n,"is",getAbs(n))
- جافا:
class GFG {
static final int CHAR_BIT = 8;
static final int SIZE_INT = 8;
static int getAbs(int n)
{
int mask = n >> (SIZE_INT * CHAR_BIT - 1);
return ((n ^ mask) - mask);
}
/* اختبار الدالة السابقة */
public static void main(String[] args)
{
int n = -6;
System.out.print("Absoute value of " + n + " is " + getAbs(n));
}
}
مصادر
- صفحة Compute the integer absolute value (abs) without branching في توثيق الخوارزميات في موقع GeeksforGeeks.