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

مشاكل double

بدأه محمد سمير في 24 يونيو 2011 · 14 رد · 738 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

الموضوع مبني على هذه المقالة http://bloodredsun.com/?p=320 و إضافة كلوجر من عندي.

مشكلة الأرقام العشرية إذا عرفت عن طريق المتغير double في لغات البرمجة:

في معظم لغات البرمجة تظهر مشكلة الأرقام العشرية إذا عرفت عن طريق المتغير double حيث أن إجراء العمليات الحسابية عليها لن يعود بأرقام دقيقة و ذلك نتيجة خطأ في إظهار بعض الأرقام بعد الفاصلة العشرية في صيغة IEEE-754

package com.bloodredsun;

public class DoubleOperation {

    public static void main(String[] args) {

        double t1 = 10.266d;
        double t2 = 10.0d;

        //Outputs 0.266
        System.out.println(t1-t2);

        double h1 = 100.266d;
        double h2 = 100.0d;

        //Outputs 0.26600000000000534
        System.out.println(h1-h2);
    }
}

لذلك الحل في لغة مثل جافا عن طريق إستخدام مكتبة BigDecimal في java.math

package com.bloodredsun;

import java.math.BigDecimal;

public class BigDecimalOperation {

        public static void main(String[] args) {

        BigDecimal t1 = new BigDecimal("10.266");
        BigDecimal t2 = new BigDecimal("10.0");

        //Outputs 0.266
        System.out.println(t1.subtract(t2));

        BigDecimal h1 = new BigDecimal("100.266");
        BigDecimal h2 = new BigDecimal("100.0");

        //Outputs 0.266
        System.out.println(h1.subtract(h2));
    }
}

لاحظ أنه يجب عليك إستخدام متغير نصي مع BigDecimal, كما يجب أن تلاحظ أن عملياتك الرياضية ستتم عن طريق إستدعء methods و ليس بإستخدام المعاملات الرياضية مباشرة.

لكن مع لغات مثل سكالا و كلوجر يمكنك التعامل مع ناتج BigDecimal مباشرة:

Scala:

package com.bloodredsun

object ScalaBigDecimalOperation {

  def main (args: Array[String]) {
    var t1 = BigDecimal("10.266")
    var t2 = BigDecimal("10.0")
    //Outputs 0.266
    println(t1 - t2)

    var h1 = BigDecimal("100.266")
    var h2 = BigDecimal("100.0")
    //Outputs 0.266
    println(h1 - h2)
  }
}

Clojure:

((import (java.math.BigDecimal)
(def t1 (BigDecimal. "10.266"))
(def t2 (BigDecimal. "10.0"))
(print (- t1 t2))

كما يمكنك تعريف دالة لتحويل الرقم المدخل لBigDecimal مباشرة:

(defn d[x](BigDecimal. (str x)))
و بذلك يمكنك كتابة معادلتك مباشرة:
user=> (- (d 10.002) (d 10.001))
0.001

M

تم تعديل هذه المشاركة بواسطة محمد سمير في 24 يونيو 2011 في 00:09

2

سبحانك اللهم و بحمدك ، أشهد أن لا إله إلا أنت ، أستغفرك ربي و أتوب إليك

مدونتي

http://www.facebook.com/brmjt

#2

نفس الموضوع في el expression

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

تسلم علاء على المرور

الآن عرفت شيء ظريف عن كلوجر و هي أنها تتعرف على متغير BigDecimal بمجرد إضافة M للعدد:

user=> (- 1.00002 1.00001)
9.999999999843467E-6

user=> (- 1.00002M 1.00001M)
0.00001M
1

سبحانك اللهم و بحمدك ، أشهد أن لا إله إلا أنت ، أستغفرك ربي و أتوب إليك

مدونتي

http://www.facebook.com/brmjt

#4

لاحظ أنك حتى عند المقارنة يجب عدم استخدام العمليات <> = أو التحويل إلى float

وإنما استخدام compareTo الموجودة في BigDecimal

يهيألي أن كلوجر واللغات الشبيهة تقوم باستخدامها أيضاً

مواضيعك دائماً جميلة أخ سمير

ولا أحب أن لا يكون إضافة على المواضيع الجميلة :)

تحياتي

1
حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#5

أما في ال C++

#include <iostream>

using namespace std;

int main(void)
{

	double d1 = 10.226;
	double d2 = 10.0;

	//Outputs 0.266
	cout << d1 - d2 << endl;

	double dx1 = 100.266;
	double dx2 = 100.0;
	//Outputs 0.266
	cout << dx1 - dx2 << endl;

	system("pause");
	return 0;
}
1
#6

حقيقه لم أفهم المشكله .. و المصدر الموجود بالرابط كبيرا جدا

#7

الفاصلة العائمة طريقة لتمثيل الأرقام العشرية مع استخدام أقل مساحة ممكنة

تفاصيل المشكلة ليست لدي بالضبط لكنها غير دقيقة في الحسابات

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

لكن المشكلة في استخدامها في البرامج التجارية لأنها لا تقدم حسابات دقيقة

لهذا الجافا تحتوي على BigDecimal لحل هذه المشكلة بالإضافة إلى مشكلة مقدار ما يمكن تخزينه في المتغير من النوع double

هذا على حد علمي القاصر وأي تعديلات أو إضافات مرحب بها :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#8

موضوع جميل اخى محمد سمير كعادة كل مواضيعك الرائعة

لى ملاحظة بسيطة :

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

System.out.printf("%.3f", h1-h2);

اقتباس

تفاصيل المشكلة ليست لدي بالضبط لكنها غير دقيقة في الحسابات

بالنسبة للدقة اظن الاولى افضل وادق لاحظ ان القص او القطع من الرقم كان فى الطباعة فقط لكن المتغير لا يزال يحمل نفس القيمة 0.26600000000000534

ويمكنك التأكد من هذا عن طريق زيادة طول الرقم فى الطباعة ("%.20f")

حتى انه فى كل العمليات الرياضية سيحتفظ بارقام عشرية دقيقة على حد علمى

لم اطلع على المصدر المرفق فى الموضوع لكن اظن الميزة الوحيدة واضحة من كلمة Big فى نوع المتغير BigDecimal اى انها مرتبطة بالحجم فقط

ملاحظة اخرى جانبية :

أحس انك تنشر دعاية فى قسم الجافا لتعلم Clojure :)

يارب يكون علاء الصالحى ما اخدش باله من الحكاية دى

انا بحاول أهدى النفوس لا اكثر هههههههههه

تحياتى


﴿وَمَا كَانَ اللَّهُ لِيُعَذِّبَهُمْ وَأَنْتَ فِيهِمْ ۚ وَمَا كَانَ اللَّهُ مُعَذِّبَهُمْ وَهُمْ يَسْتَغْفِرُونَ﴾

الأنفال ۳۳                                  
 

#9

ستبدي لك الأيام ما كنت جاهل ويأتيك بالبج من لم تخبر

خذها مني في أقرب فرصة ستجد bug جميلة في شيفرتك بسبب هذه المشكلة

وعندها ستذكرني والمدراء نواهل منك وألسنتهم تقطر من دمك

والأمر ليس مجرد طباعة

جرب أن تكتب جملة شرط وأخبرني هل حصلت على الجواب الصحيح

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#10
اقتباس

ستبدي لك الأيام ما كنت جاهل ويأتيك بالبج من لم تخبر

ههههههههههه وهل اخطأت انا لدرجة ألهمتك ان تكتب في شعرا ؟

اقتباس

وعندها ستذكرني والمدراء نواهل منك وألسنتهم تقطر من دمك

المدير اللى يفكر فى كده يبقى مات قبل ما ينتهى من تفكيره (أخوك بلطجى)

اقتباس

والأمر ليس مجرد طباعة

انا قلت انه طباعة وحجم وليس مجرد طباعة بالنسبة لجملة الشرط أجرب واوافيك بالنتيجة


﴿وَمَا كَانَ اللَّهُ لِيُعَذِّبَهُمْ وَأَنْتَ فِيهِمْ ۚ وَمَا كَانَ اللَّهُ مُعَذِّبَهُمْ وَهُمْ يَسْتَغْفِرُونَ﴾

الأنفال ۳۳                                  
 

#11

مثلما قال علاء عن دقة double مقابل BigDecimal هناك فرق و في مقالة هويدي الكفاية و زيادة.

أما كلوجر .... لا تعليق  :)

و على العموم بلاها كلوجر ... خد سكالا

سبحانك اللهم و بحمدك ، أشهد أن لا إله إلا أنت ، أستغفرك ربي و أتوب إليك

مدونتي

http://www.facebook.com/brmjt

#12
اقتباس

#include <iostream>

using namespace std;

int main(void)

{

double d1 = 10.226;

double d2 = 10.0;

//Outputs 0.266

cout << d1 - d2 << endl;

double dx1 = 100.266;

double dx2 = 100.0;

//Outputs 0.266

cout << dx1 - dx2 << endl;

system("pause");

return 0;

}

ماقاله هويدى فى صفى انا بدليل انه قال

اقتباس

حقيقه لم أفهم المشكله

اى انه حتى الان كمثلى لم نقابل هذا ال bug :)

على فكرة انا من اعطاه تقييم موجب +1 عندما رايت مشاركته لانه كتب ما كنت اود كتابته

ولازلت اصر على ان الفرق فى الحجم لا أكثر :sleep:

اقتباس

و على العموم بلاها كلوجر ... خد سكالا

وفى النهاية اعلان اخر :)

بما انك لاتخاف فلماذا اخاف انا ؟ سيبك من الجافا وتعالى معايا ++c و QT

واستمتع بالقوة والسرعة والجمال

"أعيش لمين ميت ميت" هههههههههه


﴿وَمَا كَانَ اللَّهُ لِيُعَذِّبَهُمْ وَأَنْتَ فِيهِمْ ۚ وَمَا كَانَ اللَّهُ مُعَذِّبَهُمْ وَهُمْ يَسْتَغْفِرُونَ﴾

الأنفال ۳۳                                  
 

#13

يا جماعه ...

أنا أعرف المشكله ... و أنها موجوده ... و مقتنع بذلك ..

ولكنى لا أفهم لماذا ..

نريد أحد منكم (متطوع طبعا laugh.gif) أن يقرأ المقال و يفسر لنا الحال .. (موش إنت بس يا علاء اللي بتكتب شعر :P )

و إلا .....

و إلا إتجهت لقسم ال C++ لأجد غايتى..

#14

اعلن استسلامى :wacko:

فعلا المدير كان لازم يشرب من دمى حاجة بسيطة زى دى تعدى عليا !

على كل حصل سوج تفاهم ولم انتبه لهذا الجزء

00534

فعلا مع اجراء عدة عمليات حسابية سيزيد هذا العدد تراكميا ويسبب مشكلة

مع استسلامى الا انها مشكلة الجافا وليست مشكلتى

اللبس حصل لانى اختبر الاكواد بال ++c ولا تظهر هذه المشكلة كما فى كود هويدى

وفى النهاية اشكرك محمد سمير لانك بهذا الموضوع كشفت لنا عن 2 شعراء فى القسم

اقتباس

أن يقرأ المقال و يفسر لنا الحال

وا خوفاه لتكون انت كمان شاعر يبقوا 3

يارب النت يفصل عند علاء 3 ايام لحد ماينسى الموضوع


﴿وَمَا كَانَ اللَّهُ لِيُعَذِّبَهُمْ وَأَنْتَ فِيهِمْ ۚ وَمَا كَانَ اللَّهُ مُعَذِّبَهُمْ وَهُمْ يَسْتَغْفِرُونَ﴾

الأنفال ۳۳                                  
 

#15

ههههههههههههههههههههه

ما رأيكم بتغيير اسم المنتدى إلى قسم الشعراء

عجيب الموضوع على حد علمي أن المشكلة موجود في الوثيقة القياسية الخاصة بـ IEEE

بالنسبة للمتطوع فسأحاول لكني لا أعد بشيء لانشغالي بالمشروع الجماعي الجديد

بمناسبة الإعلانات لماذا لا تشاركونا هناك؟

يبدو أني همنعكم من الكتابة في الأقسام الثانية قريباً يا حج QT :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

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