الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

الأعداد الحقيقة في ++c, هل يمكنك حل اللغز ؟!

مغلق
بدأه Khaled.Alshaya في 18 فبراير 2008 · 19 رد · 3,178 مشاهدة · في اختبر قداراتك
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم و رحمة الله و بركاته,

مرت عدة أيام لم أشارك فيها, الحقيقة أني مشغول حتى النخاع!

حتى أكون معكم صريحاً طلب من أحد الأساتذة الذين تربيت على يديهم في المنتدى طرح هذا اللغز, لن أقول اسم الشخص حتى تقوموا بحل اللغز B)

اللغز بكل بساطة يتخلل الشفرة التالية :

#include <iostream>
int main(){
	double number = 5.0;
	while( number < 7.0 ){
		number += 0.1;
		if( number == 6.0 )
			std::cout << "This Line Will Not Be Printed";
	}
	std::cout << "...................END...................";
	std::cin.get();
	return 0;
}

هل تلاحظون الشرط الذي يحويه التكرار ؟!

ذلك الشرط يحوي أمر طباعة جملة!

تلك الجملة لن يتم طباعتها أبداً!

ماهو السبب ؟!!

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 18 فبراير 2008 في 11:17

#2

السلام عليكم ورحمة الله

يمكن مش هعرف اعبر كويس لانى لسه مبتدأ فى لغة ال C++ , لكن على كل

السبب فى ذلك ان البرنامج لن يتعامل مع الرقم 0.1 وهو الزياده فى كل خطوه على انه 0.1. ولكن سيتعامل معه على حسب تعريف العدد number. بمعنى ادق , حيث ان العدد number من نوع double (اى يتضمن 15 خانة عشرية) , فان البرنامج سيتعامل مع العدد 0.1 على انه 0.0999999999999996 (وهذا نتيجة اعتبارات كثيرة منها ما يسمى فى علم التحليل العدد بالخطأ الدائرى) , ولانه يتعامل مع عدد double فسوف يتم تقريب هذا العدد الى 15 خانة عشرية ليصبح 0.1 . وطبعا هذا التقريب لا يراه الا للمستخدم , لكن فى حسابات المعالج سيتعامل مع العدد الاصلى 0.0999999999999996 . وبهذه الزيادة , فان العدد number سيزداد فى كل خطوة بهذا المقدار السابق , وبالتالى لن يمر بمرحلة القيمة 6.0 ولكن فى الحقيقة ستكون عندها القيمة بالنسبة للمعالج هى 5.9999999999999964 , وبالتالى لن يتحقق شرط جملة if وبالتالى لن يتم طباعة الجملة المشار اليها. فى الوقت الذى لو تم طباعة العدد number ستجد ان المعالج يطبعها 6.0 ولكن كما قلنا هذا للمستخدم فقط , على اساس حسب الخانات العشرية المسموح بها.

اما لو زودنا عدد الخانات العشرية المطبوعة الى 16 خانه مثلا , سنتمكن عندها من مشاهدة القيمة الفعلية للعدد number كما يراها المعالج.

ولو تم تعريف العدد number على انه float ستحدث نفس المشكلة , ولكن عند عدد خانات عشرية مقدارها 7 كما هو معروف للاعداد من النوع float.

تعديل بسيط على الكود السابق لتتمكن من مشاهدة ما يحدث بالداخل

#include <iostream>
using namespace std;
int main(){
	cout.setf(ios::fixed);
	cout.setf(ios::showpoint);
	cout.precision(16);
	double number = 5.0;
	cout << number << "\n";
	while( number < 7.0 ){
		number += 0.1;
		cout << number << "\n";
		if( number == 6.0 )
			std::cout << "This Line Will Not Be Printed";
	}
	cout << "...................END...................\n";
//	std::cin.get();
	return 0;
}

/* Output

5.0000000000000000
5.0999999999999996
5.1999999999999993
5.2999999999999989
5.3999999999999986
5.4999999999999982
5.5999999999999979
5.6999999999999975
5.7999999999999972
5.8999999999999968
5.9999999999999964 ?????
6.0999999999999961
6.1999999999999957
6.2999999999999954
6.3999999999999950
6.4999999999999947
6.5999999999999943
6.6999999999999940
6.7999999999999936
6.8999999999999932
6.9999999999999929
7.0999999999999925
...................END...................
Press any key to continue
*/

هذا والله اعلى واعلم ,,,

أشهد أن لا إله إلا الله وأشهد أن محمدا رسول الله

bnr025.gif

مـــوقـــعـــى

#3

السلام عليكم,

الأستاذ عماد حل السؤال و بذلك يرسب جميع طلاب قسم ++C :P

عموماً لمن أراد الاستزادة حول الموضوع فليقرأ حول الـ Truncation Error عند تحويل الأعداد من الصيغة التي يتم إدخالها للحاسب إلى الصيغة التي يتعامل معها المعالج أي إلى Floating Point Numbers

شكراًُ للأستاذ عماد على المشاركة,

و لا أنسى أن أشكر الأستاذ أسامة المقدم على تقديمه اللغز :)

تحياتي, و إلى اللقاء في حلقة قادمة :D

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 18 فبراير 2008 في 14:19

#4

السلام عليكم ورحمة الله

Khaled.Alshaya كتب:
السلام عليكم,

الأستاذ عماد حل السؤال و بذلك يرسب جميع طلاب قسم ++C :P

عموماً لمن أراد الاستزادة حول الموضوع فليقرأ حول الـ Truncation Error عند تحويل الأعداد من الصيغة التي يتم إدخالها للحاسب إلى الصيغة التي يتعامل معها المعالج أي إلى Floating Point Numbers

شكراًُ للأستاذ عماد على المشاركة,

و لا أنسى أن أشكر الأستاذ أسامة المقدم على تقديمه اللغز :)

تحياتي, و إلى اللقاء في حلقة قادمة :D

اسف اذا كنت حرقت لكم اللغز , لكن لم يتم ذكر اى تعليق على طريقة تقديم الحلول المقترحه. ولذلك تعاملت مع الموضوع انه سؤالا وليس لغزا.

أشهد أن لا إله إلا الله وأشهد أن محمدا رسول الله

bnr025.gif

مـــوقـــعـــى

#5

السلام عليكم ,,

أستاذ عماد شكراً لمشاركتك,

عن نفسي لا أحب إرسال الحلول إلى البريد لكسلي أولاً :lol:

ثانياً لأنه غالباً نقوم بمناقشة الحلول و الاعتراض على البعض الآخر, و لكن هذه المرة لم تبقي لنا فرصة للاعتراض :)

أما حرق اللغز فأعتقد أن طلاب الـ ++C قد رسبوا في المادة و انتهينا من الموضوع :D

تحياتي,

#6

السلام عليكم:

جربت الكود وتتبعت تنفيذه فعلا الارقام تظهر في الكمبايلر بالشكل التالي:

number 5.0000000000000000 double

number 5.0999999999999996 double

number 5.0999999999999996 double

والغريب عندما تكتب الكود بهذه الطريقه تظهر الارقام صحيحة.

while( number < 7.0 )

{





number +=0.1;



cout << number<<endl;



}

لكن لم اعرف حل المشكلة ياخالد.

tvquran_6.gif

#7

السلام عليكم ,,

أهلاً أخ فهد,

بالنسبة للحل فهي ليست مشكلة أصلاً حتى يوجد لها حل :huh:

سبب حصول ذلك هو تمثيل الأعداد داخل الحاسب(المعالج) و هذه هي مشكلة الأعداد الحقيقة في المعالجات من وجهة نظر المبرمج,

إذا كنت من محبي الرياضيات هناك الكثير من المكتبات التي توفر أعداد ذات فاصلة مع دقة غير محدودة إلا بذاكرة الجهاز الذي لديك,

أشهرها على ما أذكر GNU MP و لكن لم أتعامل معها من قبل, تعاملت مع مكتبات توفر أعداداً صحيحة غير محدودة الدقة و لكنها ليست بجودة مكتبة GNU على كل حال,

بالمناسبة ماذا تقصد بـ :

اقتباس
والغريب عندما تكتب الكود بهذه الطريقه تظهر الارقام صحيحة.

تحياتي ,,

#8

أقصد هذا الكود.

#include <iostream>
int main(){
double number = 5.0;
while( number < 7.0 ){
number += 0.1;
std::cout <<number<<std::endl ;
}
std::cout << "...................END...................";
std::cin.get();
return 0;
}
tvquran_6.gif

#9

السلام عليكم ورحمة الله

أخى الفاضل فهد الشلوي

ده طبيعى جدا ان ترى الاعداد الناتجه من برنامجك تبدوا صحيحه , لكن مش هى دى الارقام اللى بيشوفها المعالج. مافيش حاجه غريبه. ارجع تانى واظهر النتائج حتى 16 رقم عشرى , سترى الارقام التى يراها المعالج.

اما عن حل المشكله , فانا اعتبر هذا الخطأ , خطأ منطقى وليس برمجى , بمعنى ان البرنامج لن يعترض عليه , ولكن ستحصل على نتائج خاطئه, وذلك لعدم الاخذ فى الحسبان خصائص الاعداد الحقيقية وحقيقة تعريفها للمعالج. وفى الحقيقة هذا السؤال لم يكن مفاجئا لى , ولكنى قابلته بنفسى فى احدى برامجى فى مرحلة الماجستير , واخذت يومين تحليل فى البرنامج الى ان اكتشفت المشكله.

ولكن لو مصر انك تتعامل مع هذا الكود , وتقوم بتصحيحة ليعطى نتائج صحيحه. فيجب عليك عند مقارنة العددين number و 6.0 فى جملة if ان تقوم بعمل تقريب للعدد number اولا الى عدد خانات عشرية مثل الرقم المقارن به وهو 6.0 كما قلنا. عندها سيعمل الكود بشكل طبيعى.

كمثال

#include <iostream>
#include <cmath>

double round(double parent, int n)
{
	double child;
	child=-floor(-parent*pow(10,n)+0.5)/pow(10,n);
	return child;
}

int main(){
	double number = 5.0;
	while( number < 7.0 ){
		number += 0.1;
		std::cout << number << std::endl;
		if( round(number,1) == 6.0 )
			std::cout << "This Line Will Not Be Printed\n";
	}
	std::cout << "...................END...................";
	return 0;
}

ومعلش انى عرفت دالة round بهذا الشكل , لانى لا اعلم كيفية استدعائها فى لغة ال C++

والله اعلى واعلم ,,,

تم تعديل هذه المشاركة بواسطة عماد حمدي احمد في 18 فبراير 2008 في 15:40 — السبب: خطأ بسيط

أشهد أن لا إله إلا الله وأشهد أن محمدا رسول الله

bnr025.gif

مـــوقـــعـــى

#10

السلام عليكم ,,

أعتقد أن الكائن يقوم بعملية تقريب للعدد, و لكن حقيقة لا أعرف كيف يقوم بذلك,

أنا أبحث في ملفات الـ header الخاصة بـ ++g لربما أصل إلى شيء :)

#11

فهم كلامك يا عماد بارك الله فيك.

هل تقصد ياخالد ان cout تقوم بالتصحيح.

tvquran_6.gif

#12
اقتباس
هل تقصد ياخالد ان cout تقوم بالتصحيح.

نعم, بالمناسبة هناك manipulator اسمه setprecision يمكنك عن طريقه تحديد عدد الخانات التي سيتم طباعتها بعد الفاصلة و لكن لا أدري إن كان يقوم بعملية تقريب للعدد أم لا!

#13

السلام عليكم ورحمة الله

اخى الفاضل cout تقوم بالتصيح فى المخرجات فقط لاغير , اى للمستخدم فقط , ولكن تظل القيم بالنسبة للمعالج كما هى قبل التصحيح.

والله اعلى واعلم ,,,

أشهد أن لا إله إلا الله وأشهد أن محمدا رسول الله

bnr025.gif

مـــوقـــعـــى

#14
اقتباس
أما حرق اللغز فأعتقد أن طلاب الـ ++C قد رسبوا في المادة و انتهينا من الموضوع

خالد اللغز وضع بتاريخ اليوم, 11:13 AM .. والاخ عماد اجاب على اللغز بعد ساعه من طرحه وحتى انه لم تسمح الفرصة لي للدخول الى المنتدى بسبب الدراسة ..

يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..

#15

لقد تناقشنا في هذا الموضوع من قبل يا خالد

أظن كان ذلك عند نقاشنا حول ترجمة كلمة float وكنت وقتها أريد وضع هذا اللغز لكن ظننت أن الأمر أصبح واضحا بعد نقاشنا فيه فلم أضعه

وعموما فمن المعلوم أنه لا يسمح أبدا باستخدام علامة "==" في التعامل مع float أو double بسبب هذه المشكلة

من أقوال الأئمة

الإمام علي بن أبي طالب -رضي الله عنه-: "الناس ثلاثة : فعالم رباني ، ومتعلم على سبيل النجاة ، وهمج رِعاع غوغاء أتباع كل ناعق ، يميلون مع كل ريح ، لم يستضيئوا بنور العلم ، ولم يلجئوا إلى ركن وثيق".

الإمام مالك -رحمه الله- : " لن يصلح آخر هذه الأمة إلا بما أصلح به أولها ".

الإمام الأوزاعي -رحمه الله- : " عليك بآثار من سلف وإن رفضك الناس وإياك وآراء الرجال وإن زخرفوه لك بالقول ".

الإمام الفضيل بن عياض -رحمه الله- : " عليك بطرق الهدى و لا يضرك قلة السالكين و إياك و طرق الضلالة ولا يغرك كثرة الهالكين ".

علامة الزمان الإمام الألباني -رحمه الله- : " إن الخلاص إلى أيدي هؤلاء الشباب يتمثل في أمرين لا ثالث لهما ؛ التصفية والتربية ".

وكل خير في اتباع من سلف وكل شر في ابتداع من خلف

#16
اقتباس
السبب فى ذلك ان البرنامج لن يتعامل مع الرقم 0.1 وهو الزياده فى كل خطوه على انه 0.1. ولكن سيتعامل معه على حسب تعريف العدد number. بمعنى ادق , حيث ان العدد number من نوع double (اى يتضمن 15 خانة عشرية) , فان البرنامج سيتعامل مع العدد 0.1 على انه 0.0999999999999996 (وهذا نتيجة اعتبارات كثيرة منها ما يسمى فى علم التحليل العدد بالخطأ الدائرى) , ولانه يتعامل مع عدد double فسوف يتم تقريب هذا العدد الى 15 خانة عشرية ليصبح 0.1 . وطبعا هذا التقريب لا يراه الا للمستخدم , لكن فى حسابات المعالج سيتعامل مع العدد الاصلى 0.0999999999999996 . وبهذه الزيادة , فان العدد number سيزداد فى كل خطوة بهذا المقدار السابق , وبالتالى لن يمر بمرحلة القيمة 6.0 ولكن فى الحقيقة ستكون عندها القيمة بالنسبة للمعالج هى 5.9999999999999964 , وبالتالى لن يتحقق شرط جملة if وبالتالى لن يتم طباعة الجملة المشار اليها. فى الوقت الذى لو تم طباعة العدد number ستجد ان المعالج يطبعها 6.0 ولكن كما قلنا هذا للمستخدم فقط , على اساس حسب الخانات العشرية المسموح بها.

اما لو زودنا عدد الخانات العشرية المطبوعة الى 16 خانه مثلا , سنتمكن عندها من مشاهدة القيمة الفعلية للعدد number كما يراها المعالج.

أنا أول وحدة حلت اللغز للأستاذ الكريم أسامة قبل يومين,,,شو الفرق استاذنا بينات كلامي وكلام الأخ المحترم عماد؟؟؟ و مسألة التقريب اللي انا ذاكرتها شفهيا وبسرعة؟ لكن المشرف عماد كان عنده الوقت المناسب لكتابة الموضوع بالتفصيل؟ :mellow:

طبعاً الأخ عماد اول واحد حل اللغز بالعام لكن طالما حله صحيح فأنا اول وحدة قدمت الحل للأخ الأستاذ اسامة وكان مناسبة اللغز كرماً من الأستاذ أسامة حين نقاش لغزي اللي انا واضعته مسبقاً

========

وبعدينه يا اخوتي الكرام انا نوهت للأخ الفاضل أسامة بأن تعين قيمة ذات فاصلة عائمة لحارس التكرار عيب برمجي هندسياً وحرفياً Bad Practice عند العموم

=========

تمنياتي لكم

[وسط]

♥ Countess ♥

57899411.gif

♥

[/وسط]

#17

السلام عليكم ,,

أخ باسم :

اقتباس
لقد تناقشنا في هذا الموضوع من قبل يا خالد

أظن كان ذلك عند نقاشنا حول ترجمة كلمة float وكنت وقتها أريد وضع هذا اللغز لكن ظننت أن الأمر أصبح واضحا بعد نقاشنا فيه فلم أضعه

وعموما فمن المعلوم أنه لا يسمح أبدا باستخدام علامة "==" في التعامل مع float أو double بسبب هذه المشكلة

جميل, من الممكن أن الكثير من الأشخاص لم يشاهدوا النقاش الذي حصل في موضوع الترجمة :)

بالمناسبة يا باسم هل قرأت مشاركتي حول تسمية الأعداد العشرية و من بدأ بها ثم تخلى عنها في الموضوع الأول للترجمة :lol:

أخت رغد :

اقتباس
أنا أول وحدة حلت اللغز للأستاذ الكريم أسامة قبل يومين,,,شو الفرق استاذنا بينات كلامي وكلام الأخ المحترم عماد؟؟؟ و مسألة التقريب اللي انا ذاكرتها شفهيا وبسرعة؟ لكن المشرف عماد كان عنده الوقت المناسب لكتابة الموضوع بالتفصيل؟ 004.gif

طبعاً الأخ عماد اول واحد حل اللغز بالعام لكن طالما حله صحيح فأنا اول وحدة قدمت الحل للأخ الأستاذ اسامة وكان مناسبة اللغز كرماً من الأستاذ أسامة حين نقاش لغزي اللي انا واضعته مسبقاً

عموماً حصل خير, و بالمناسبة لست أول من تطرق للمسألة في القسم :P

هذا أول موضوع لي في القسم منذ اشتركت في المنتدى :)

فكر قبل الإجابة على السؤال

ولكن بما أن الموضوع السابق قد مضى عليه أكثر من سنة, فرحت بطلب الأخ أسامة حول الموضوع لتنشيط الذاكرة و عرض الموضوع على الأعضاء الذين لم يقرأوا المواضيع القديمة في القسم, و خصوصاً أنه من المواضيع القيمة.

سعدت بمشاركاتكم,

تحياتي,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 19 فبراير 2008 في 07:07

#18
رغـــــــــد كتب:
أنا أول وحدة حلت اللغز للأستاذ الكريم أسامة قبل يومين,,,

========

وبعدينه يا اخوتي الكرام انا نوهت للأخ الفاضل أسامة بأن تعين قيمة ذات فاصلة عائمة لحارس التكرار عيب برمجي هندسياً وحرفياً Bad Practice عند العموم

نعم هذا ما حدث قبل يومين أو ثلاثة من الأن، فقد ذكرت الأخت الفاضلة رغـــــــــد أن مسألة التقريب هى السبب فى ذلك

تم تعديل هذه المشاركة بواسطة Eng. Usama El-Mokadem في 19 فبراير 2008 في 07:32

Eng. Usama El-Mokadem

Nothing is impossible, the word impossible itself says that: I M - Possible

#19

السلام عليكم,

لو سمحتوا يا أخوان أين أجد مشاركة الأخت رغد حول الموضوع :wacko:

#20

بتعرفو يا جماعة؟؟!!

انا واجهتني هالمشكلة من زمان

وقتها حسيت انو المعالج فيه خلل

على كل حال .. جزاكم الله عنا خيرا

دولة الخلافة الاسلامية في المخاض الاخير وميلادها قريب

حزب التحرير : التزم الطريق الصحيح الشرعي الوحيد لاعادة دولة الخلافة الاسلامية .

الامة الاسلامية متعطشة لقيادة مخلصة لتذوق حلاوة النصر ولن يكون ذلك الا بعودة الخلافة الاسلامية

الامة الاسلامية تحتاج لاحداث تسحقها سحقا وتمعسها معسا لتفكر تفكيرا جماعيا بالتغير لان وحدة المشاعر لوحدها لاتكفي وهذة الاحداث كلها خير

هذا الموضوع مغلق.

مواضيع مشابهة