إستخدام double و float: كيف يؤدي إلى خسارة حتمية أو أرباح زائفة

3
مصطفى محمد
  • برمجة
  • 2016-08-13T18:24:57+00:00
  • المزيد
    • رابط مختصر

إستخدام double و float: كيف يؤدي إلى خسارة حتمية أو أرباح زائفة

www.oolom.com/3930/%D8%A5%D8%B...

كشف طريقة التتخلص من وجود فروقات في الحسابات عند إستخدام float و double و ضبط الحسابات 100% دون التعرض لخسائر أو مشاكل في البرامج.


التعليقات

  • الأفضل
  • الأحدث
  • الأقدم
1
First Last
  • 2016-08-13T22:44:24+00:00
  • 2016-08-13T22:49:45+00:00
  • المزيد
    • رابط مختصر

استخدام BigDecimal للأسباب التي ذكرتها ليس حلا.

أي نظام رقمي سيعاني مشاكل من تمثيل بعض الكسور. النظام العشري لن يستطيع تمثيل 1/3 مثلا.

BigDecimal لن تفيد في ذلك. إذا كانت النسبة مهمة يجب تخزينها كنسبة (Rational).

ما ذكرته من مشاكل محتملة:

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

السبب عندك هو أن Double.toString()‎ ترجع أدق تمثيل عشري لازم لمنع الاختلاط. الحل الصحيح هو التقريب للخانات العشرية المرادة عند العرض.

  • في الأنظمة الحسابية يحدث إختلاف طفيف يكلف المُنشأة الكثير من الوقت و المال في محاولة إيجاد سبب الفرق.

صحيح. BigDecimal واجبة عند التعامل مع المبالغ المالية.

  • في الأنظمة الطبية يؤدي إلى حصول المريض على جُرعة زائدة أو ناقصة.

الحلقة الضعيفة هي دقة الجهاز الذي يضخ الجرعة.

  • في الأنظمة العسكرية يؤدي إلى سقوط صواريخ في غير ما خُطط له.

صحيح أن الاحداثيات المستخدمة عشرية. النوع المستخدم هنا عادة ما يكون FixedPoint.

  • في أنظمة الفضاء يؤدي إلى إنحراف مكوك فضائي عن مساره!

لم تظن أن Decimal ستحل المشكلة؟ نفاثات المكوك لا تعبأ إن كنت تستخدم Decimal أو Binary Float أو حتى Fixed.

على أي حال دقة النوع المستخدم أعلى من دقة التحكم ويلزمك تصحيح المسار دائما.

نظم التحكم في الطيران الجارية بالفعل تستعمل binary floating point على عكس ما تلمح له.

النظام العشري لن تحتاجه إلا عندما تتعامل مع وحدات نحن صنعناها (فائدة تراكمية، خطوط طول وعرض).

ما عدا ذلك فكل النظم الرقمية سواسية.

0
مصطفى محمد
  • 2016-08-14T04:48:14+00:00
  • المزيد
    • رابط مختصر

شُكراً لك @a3f

ردُّك مليء بالمعلومات القيمة، جُزيت خيراً.

أعلم تماماً أن BigDecimal ليست الحل الوحيد، وليست الأسهل ولا الأفضل حتى. توقّعتُ أن هناك من سيُعلّق متحدثاً عن تلافي إستخدام الكسور و استبدالها بأرقام صحيحة أو استخدام Round أكثر ولكن ردّك أسعدني.

المشاكِل المذكورة هي ما قد يحدُث عند استخدام double أو float في هكذا أنظمة، وليس حلها دائماً وحيد، هناك حُلول كثيرة منها ما ذكرت.

أثريتَ النقاش أخي @a3f و قد اسعدني ردُّك مرة أخرى شكراً لك.

0
Joe T T
  • 2016-08-13T19:39:06+00:00
  • المزيد
    • رابط مختصر

شكرًا على مجهودك، فقط لم توضح أنه لمبرمجي Java؛ عندما تحدثت عن الحل تحدثتَ BigDecimal مباشرًا،

على الجانب في Go وضعواْ نوعًا افتراضيًا complex128، وcomplex64 يحل المشكلة بسهولة وببساطة:

package main

import "fmt"

func main() {
    num := complex128(6)
    fmt.Printf("%f", num * 0.3)
}

التجربة:

https://play.golang.org/p/H...
1
مصطفى محمد
  • 2016-08-14T14:10:23+00:00
  • المزيد
    • رابط مختصر

فعلاً @يوسف سيد

القسم الذي كتبت به هذه التدوينة هو جافا، ولكن العنوان و الرابط لا يوضح هذه المعلومة.

سأجعل الأمور أوضح مستقبلاً بإذن الله.

0
Joe T T
  • 2016-08-13T19:41:17+00:00
  • 2016-08-13T19:43:55+00:00
  • المزيد
    • رابط مختصر

أيضًا float64 يعمل لأن الرقم قصير:

func main() {
    num := float64(6)
    fmt.Printf("%f", num * 0.3)
}
0
First Last
  • 2016-08-13T22:51:46+00:00
  • المزيد
    • رابط مختصر

لا أظن printf في Go تختلف عن أمها في C:

‎%f تقرب ل 6 خانات عشرية ما لم يذكر خلاف ذلك. ذلك على عكس الجافا التي ترجع أدق تمثيل عشري لازم لمنع الاختلاط.

حجم النوع ليس له أي علاقة. أرجح أن Complex تستخدم Binary Floating Point لشقيها كذلك.

حتى لو استخدمت BigBinary المشكلة مع 0.3 موجودة. وهي موجودة مع قيم أخرى في كل النظم. راجع تعليقي الآخر.

0
Joe T T
  • 2016-08-14T07:57:34+00:00
  • 2016-08-14T08:03:07+00:00
  • المزيد
    • رابط مختصر

لا أظن printf في Go تختلف عن أمها في C:

‎%f تقرب ل 6 خانات عشرية ما لم يذكر خلاف ذلك. ذلك على عكس الجافا التي ترجع أدق تمثيل عشري لازم لمنع الاختلاط.

ليس تمامًا Go يمكنها معرفة النوع قبل الطباعة، وPrintf تختلف تمامًا عن C وC ليست أم Go هي أختها الكبيرة :)، انظر هنا:

https://golang.org/pkg/fmt

والمصدر:

https://github.com/golang/g...

تستخدم Go معيار IEEE-754 في تمثيل الأرقام float32، float64 ..، قرأتُ الفرق أنّ Complex تحاول تقريب العدد إلى عدد حقيقي مع نسبة خطأ صغيرة جدًا على الكسور الصغير وللحقيقة لا أعرف كيف تمامًا، أستخدمها عند طباعة رقم حقيقي وإن كانت القسمة كبيرة أستخدم الحزمة math/big، في المثال السابق عند الطباعة بـPrintf سيكون الناتج:

1.800000+0.000000i

وعندما أستخدم الدالة real على الرقم النهائي لأحصل على أقرب float64 حقيقي، سأحصل على:

1.800000

0
First Last
  • 2016-08-14T08:12:18+00:00
  • 2016-08-14T08:12:41+00:00
  • المزيد
    • رابط مختصر

من توثيق Go:

The default precision for %e and %f is 6

complex128 is the set of all complex numbers with float64 real and imaginary parts.

ما ذكرته ليس له علاقة بالموضوع. العدد معروض عندك كذلك لأن printf تقربه.

0
Joe T T
  • 2016-08-14T08:16:00+00:00
  • 2016-08-14T08:26:24+00:00
  • المزيد
    • رابط مختصر

For floating-point values, width sets the minimum width of the field and precision sets the number of places after the decimal, if appropriate, except that for %g/%G it sets the total number of digits. For example, given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5. The default precision for %e and %f is 6; for %g it is the smallest number of digits necessary to identify the value uniquely.

ثم شاهد:

For complex numbers, the width and precision apply to the two components independently and the result is parenthesized, so %f applied to 1.2+3.4i produces (1.200000+3.400000i).

0
First Last
  • 2016-08-14T08:39:09+00:00
  • 2016-08-14T08:59:29+00:00
  • المزيد
    • رابط مختصر

ما الأمر الذي لم تفهمه؟ Go تعرض النوع كذلك لأن Printf تقربه ليس لأنه مخزن بدقة. ما ذكرته أنت عن الدقة الزائدة لComplex و Float64 ليس له علاقة بعرض العدد ك 1.8.

0
Joe T T
  • 2016-08-14T09:09:32+00:00
  • المزيد
    • رابط مختصر

آه حسنًا الآن فهمت، لكن لم أفهم بعد لما نستخدم cmplx.Pow بدلًا من math.Pow يقولون أنها أكثر دقة complex128 يعتمد على وحدتين!.

0
First Last
  • 2016-08-14T09:26:12+00:00
  • المزيد
    • رابط مختصر

النوع Complex لتمثيل الأعداد المركبة. للأعداد الحقيقية (حيث الشطر التخيلي صفر) لا فرق بين إستخدام pow الخاصة به و pow الخاصة ب float عادي.

الأعداد المركبة منهج مقرر في الثانوية العامة المصرية لطلبة الرياضيات.

0
Joe T T
  • 2016-08-14T09:35:08+00:00
  • 2016-08-14T11:45:42+00:00
  • المزيد
    • رابط مختصر

آه لا أعرف كيف خلطُ الأمور، نعم هي مقرر على الصف الأول درستها بالفعل هذا العام:

fmt.Println(real(cmplx.Sqrt(-1) * cmplx.Sqrt(-1))) // -1
fmt.Println(math.Sqrt(-1) * math.Sqrt(-1)) // NaN

سأقيم نفسي بالسالب إن قدرتُ، متأكد أني قرأتُ هذا الكلام في أحد المدونات،


اقرأ أيضًا

  • استخدام اللغة العربية في برمجة الحاسب الآلي
  • جافا سكريبت، كيف يمكنني احترافها، وما هي استخداماتها؟
  • كيف يعمل الكومبايلر؟
  • كيف ابدأ دراشة تحليل البيانات؟
  • كيف أثق في فريقي البرمجي ؟!

برمجة

مجتمع للمبرمجين من جميع المستويات لتبادل المعرفة والخبرات. ناقش لغات البرمجة المختلفة، الحلول البرمجية، والمشاريع.

25.4 ألف متابع

أطلق موقعك الإلكتروني في دقائق

صمم موقعك كاملا بالسحب والإفلات بدون خبرة برمجية، واحجز مكانك على الإنترنت.

أنشئ موقعك الآن

انسخ هذا الرابط:

تنبيه