إحدى المشكلات الرئيسية في العمل مع الأرقام العشرية الممثلة في الكود الثنائي هي مشكلة تقريب الرقم الثنائي إلى قيمة الرقم العشري القابل للتمثيل الأقرب إلى رقم عشري مستدير بشكل صحيح. نناقش أدناه هذه المشكلة ونعطي خوارزمية بسيطة للتقريب المناسب. يتضح تشغيل الخوارزمية بواسطة برنامج اختبار في C ++.
تذكر أن الرقم العشري القابل للتمثيل هو رقم يمكن تمثيل قيمته بدقة بواسطة الكود الثنائي. لذلك ، الرقم 0.125 يساوي تمامًا الرقم الثنائي 0.001. يمكن أيضًا القول بأن قيمة أي رقم ثنائي
y تساوي عدد عشري يمكن تمثيله
x . على سبيل المثال ، قيمة الرقم الثنائي
y = 1.001101 * 2 ^ -3 تساوي قيمة الرقم العشري القابل للتمثيل
x = 0.150390625.
نقول أن الرقم الثنائي y مكافئ للرقم العشري
x . على العكس ، الرقم العشري
x مكافئ للرقم الثنائي
y .
دعونا نرى ما يحدث برقم عشري عند إدخاله من وحدة التحكم ، أو عندما يظهر في البرنامج على أنه ثابت.
يتم تحويل (تحويل) أي رقم عشري بواسطة المحول البرمجي إلى التنسيق المحدد بواسطة المبرمج. نظرًا لأن الأرقام الثنائية تتم معالجتها بشكل أسرع في جهاز كمبيوتر ، يتم تحويل الرقم العشري للإدخال ، في أغلب الأحيان ، إما إلى تنسيق نقطة ثابتة (بما في ذلك int) ، أو إلى أحد تنسيقات الفاصلة العائمة - مفرد ، مزدوج ، أو إلى تنسيق ثنائي آخر .
وفقًا لمعيار IEEE754 ، يتم تمثيل الأرقام الحقيقية بالتنسيق الداخلي للجهاز في شكل ثنائي عادي. لذلك ، يمكن تمثيل رقم حقيقي موجب ثنائي
y كـ
y = b0.b1 ... bp * 2 ^ e (b0 ≠ 0).يمكن تمثيل نفس الرقم على أنه
0.b0b1 ... bp * 2 ^ (e + 1) (b0 ≠ 0) إذا
e + 1> 0 و
0.b0b1 ... bp * 2 ^ e (b0 ≠ 0) إذا
ه <0 .
كذلك سوف نلتزم الرأي الثاني ، منذ ذلك الحين في برنامج اختبار C ++ الخاص بنا أدناه ، هناك دالة q = frexp (x ، & e) ، والتي تتيح لنا تحديد قيمة الأس الأس في الرقم الثنائي الذي يمثل
b0.b1 ... bp * 2 ^ e .
لذلك ، المكافئ العشري لأي رقم ثنائي
ثابت y = 0.b0b1 ... bp * 2 ^ e (b0 ≠ 0) يساوي بعض الأرقام العشرية المقيسة
x = 0.d0d1 ... dN ... dn * 10 ^ E (d0 ≠ 0).على سبيل المثال ، الرقم
y = 0.1001101 * 2 ^ -2 مكافئ للرقم العشري
القابل للتمثيل x = 0.150390625 .
للحصول على الرقم
Xr من
x مساوٍ للرقم مقربة إلى أرقام هامة
N ، يجب ضرب
X بعامل
10 ^ k ، حيث
k = NE . يعد ذلك ضروريًا حتى يحتوي الرقم الناتج على جزء صحيح مع أرقام
N مهمة ، والتي يمكن تقريبها إلى أقرب عدد صحيح. يجب بعد ذلك تخفيض العدد الصحيح المستدير إلى المقياس السابق بضربه بـ
10 ^ -k . رياضيا ، يمكن كتابة ذلك بالصيغة التالية:
X = [x * 10 ^ k + 0.5] * 10 ^ -k = [y * 10 ^ k + 0.5] * 10 ^ -k ، حيث [] هو الجزء الصحيح من الرقم.
يمكن إثبات أن عدد ثنائي صحيح
B يحتوي على
m رقمين ثنائيين يساوي قيمة الرقم العشري
D ، الذي يحتوي على
n = ⌊m * log2⌋ المنازل العشرية ، بشرط أن
B <10 ^ n. ويساوي n = n + 1 ، بشرط أن
B ≥ 10 ^ n . في الحسابات ، يمكننا أن نأخذ
log2≈0.301 .
نحدد قيمة
k بناءً على المعلومات المتاحة في التمثيل الثنائي لـ
y . في صيغة
k ، تُعرف دقة التقريب لـ
N ، لذلك نحن بحاجة إلى تحديد الأس
.يتم تحديد الأس
E من العلاقة:
E = ⌊e * 0.301⌋ .
يبقى أن نأخذ في الاعتبار الظروف التالية. إذا كانت
x * 10 ^ k = X> 10 ^ N ، فأنت بحاجة إلى ضربها في
10 ^ (- 1) وضبط معامل
k . نحصل على
X = X * 10 ^ (- 1) ، k = k-1 .
سيكون العدد المستدير مساوياً
Xr = X * 10 ^ (- k) .
نتيجة لذلك ، نحصل على الخوارزمية البسيطة التالية للتقريب العشري الصحيح للأرقام الحقيقية الثنائية. الخوارزمية مناسبة لأي تنسيق رقمي ثنائي بدقة تقريبية عشرية محددة بدقة
N.عند المدخل:
دقة التقريب العشري
N ؛
هو رقم ثنائي بالتنسيق
y = 0.b0b1 ... bp * 2 ^ e (b0 ≠ 0) .
الإخراج: رقم عشري مدور
X = 0.d0d1 ... dN * 10 ^ E.- 1. حدد الأس الأسي للرقم الثنائي y ؛
2. E = *e * 0.3⌋ ؛
3. ك = NE ؛
4. س = س * 10 ^ ك ؛
5. إذا كانت علامة <10 ^ N ، ثم العنصر 8 ؛
6. X = X * 10 ^ -1 ؛
7. ك = ك -1 ؛
8. Xr = [X + 0.5] * 10 ^ (- k) ؛
ينتهي.
- في الخوارزمية أعلاه ، يكون الرقم
Xr هو الرقم العشري
القابل للتمثيل الأقرب إلى الرقم ، وهو التقريب الصحيح للرقم
x ، والذي بدوره يكون المكافئ العشري للرقم
y .
نظرًا لأننا معتادون على العمل مع الأرقام العشرية ، إذن ، كقاعدة عامة ، فإن تدفق المدخلات هو أرقام عشرية بالضبط. في الإخراج ، نريد الحصول على أرقام عشرية أيضًا. على سبيل المثال ، كما في Excel. ولكن بعد تحويل الأرقام العشرية إلى رمز ثنائي ، يتم تحويلها عادةً بشكل لا رجعة فيه. نتيجة لذلك ، قد لا يتزامن التقريب المحول إلى أرقام ثنائية مع التقريب الصحيح للأرقام المطبوعة على وحدة التحكم. ينطبق هذا بشكل أساسي على الحالات التي نحاول فيها تقريب الرقم العشري إلى أقصى عدد ممكن من الأرقام المهمة. للأفراد ، هذا هو 7 ، ومضاعفة 15.
يمكن التحقق من ذلك جيدًا في برنامج الاختبار أدناه ، والذي كتبه المؤلف في C ++.
في برنامج الاختبار ، عند الطلب ، يتم إدخال ما يلي في وحدة التحكم:
- دقة التقريب العشري
N للرقم
X ، وهو أقرب رقم يمكن تمثيله من المكافئ الثنائي للرقم
x ؛
هو الرقم
العاشر في شكل تعسفي.
تحت الرقم العشري الذي تم إدخاله
x ، تتم طباعة الرقم
X ، وهو الرقم القابل للتمثيل الأقرب إلى
x (انظر لقطة الشاشة أدناه).
يتم التقريب على الرقم
X ، لأن يتم فقد القيمة الدقيقة لـ
x في التحويل الثنائي.
العوائد:
- الرقم العشري بالتنسيق
Xr = M * 10 ^ (N + e) ، حيث
M هو رقم عشري صحيح مع أرقام
N كبيرة ؛
هو الرقم
xr ، الذي يساوي الرقم القابل للتمثيل الأقرب إلى المكافئ الثنائي المقيس للرقم
X.
في لقطة الشاشة:
N = 15 - عدد الأرقام العشرية الهامة التي يتم تقريب الرقم العشري للإدخال إليها.
x = 7.123456789098765321 e-89 هو الرقم العشري الذي نود تقريبه إلى 15 رقمًا مهمًا.
X = 7.12345678909876559 e-089 - رقم عشري يمكن تمثيله ، وقيمته مساوية للرقم الثنائي الذي تم الحصول عليه عن طريق تحويل الرقم x إلى التنسيق p = 53.
Xr = x = 712345678909877e-103 - عدد سلالة النجم الصحيح الذي تم الحصول عليه عن طريق تقريب الرقم X.
xr = x = 7.12345678909877e-089 - الرقم الذي تم الحصول عليه عن طريق تطبيع المكافئ الثنائي للرقم العشري Xr. هذا هو الأقرب إلى Xr.
فيما يلي رمز برنامج الاختبار للتقريب الصحيح للأرقام العشرية الممثلة في الكود الثنائي في C ++.
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <iomanip>
using namespace std;
int main()
{
double q,x,xr,X;
unsigned long long int Xr;
int N,p,E,e,k;
cout <<"Input a binary precision p=";
cin>>p;
cout <<"Input a decimal precision N=";
cin>>N;
cout <<endl<<"Input a number and press ENTER:"<<"\n"<<"x= ";
cin>>x;
cout<<"X= "<< setprecision(18)<<x << '\n';
q=frexp (x, &e);
E =static_cast <int> (e*0.301);
k=N-E;
if (E<0) //for format xr=d0.d1...dN*10^E (d0≠0).
k=k+1;
X=x*pow(10,k);
if (X > pow (10,N)){
X=X/10;
k=k-1;
}
X=X+0.5;
Xr=static_cast <unsigned long long int> (X);
xr=Xr*pow(10,-k);
cout<<endl <<"Xr= "<<Xr<<"e"<<-k<<'\n';
cout<<"xr="<<xr<<'\n';
system("pause");
return 0;
}
pow(10,k). ,
k , ,
10^k,
5^k.