خلل في حاسبة Google، يمكن أن يطفو مقابل.مضاعفة يكون السبب المحتمل؟

StackOverflow https://stackoverflow.com/questions/27095

  •  09-06-2019
  •  | 
  •  

سؤال

لقد فعلت هذا من أجل الركلات فقط (لذلك، ليس هذا سؤالًا تمامًا، أستطيع أن أرى أن عملية التخفيض تحدث بالفعل) ولكن بدلاً من اكتشاف Google الجديد عجز لكى يفعل الرياضيات بشكل صحيح (افحصها!وفقًا لـ google 500,000,000,000,002 - 500,000,000,000,001 = 0)، اعتقدت أنني سأجرب ما يلي في لغة C لتشغيل القليل من النظرية.

int main()
{
   char* a = "399999999999999";
   char* b = "399999999999998";

   float da = atof(a);
   float db = atof(b);

   printf("%s - %s = %f\n", a, b, da-db);

   a = "500000000000002";
   b = "500000000000001";
   da = atof(a);
   db = atof(b);
   printf("%s - %s = %f\n", a, b, da-db);
}

عند تشغيل هذا البرنامج تحصل على ما يلي

   399999999999999 - 399999999999998 = 0.000000
   500000000000002 - 500000000000001 = 0.000000

يبدو أن Google تستخدم دقة عائمة بسيطة تبلغ 32 بت (الخطأ هنا)، إذا قمت بتبديل التعويم لمضاعفة في الكود أعلاه، فستصلح المشكلة!هل يمكن أن يكون هذا هو؟

/ النائب

هل كانت مفيدة؟

المحلول

في C#، جرب (double.maxvalue == (double.maxvalue - 100)) ، ستصبح صحيحًا ...

ولكن هذا ما يفترض أن يكون:

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

بالتفكير في الأمر، لديك 64 بت يمثل رقمًا أكبر من 2^64 (double.maxvalue)، لذلك من المتوقع عدم الدقة.

نصائح أخرى

للمزيد من هذا النوع من السخافة، راجع هذه المقالة الرائعة المتعلقة بآلة حاسبة Windows.

عند تغيير الدواخل، لا أحد يلاحظ

تم إلقاؤه بالكامل من Calc - المحرك الحسابي - وأعاد كتابته من الصفر.تم استبدال مكتبة Point Point القياسية IEEE بمكتبة الحساب التعسفي.تم ذلك بعد أن استمر الناس في كتابة مقالات HA -HA حول كيفية عدم استطاعت CALC أن تفعل الحساب العشري بشكل صحيح ، على سبيل المثال ، أدى الحوسبة 10.21 - 10.2 إلى 0.0100000000000016.

يبدو أن Google تستخدم دقة عائمة بسيطة تبلغ 32 بت (الخطأ هنا)، إذا قمت بتبديل التعويم لمضاعفة في الكود أعلاه، فستصلح المشكلة!هل يمكن أن يكون هذا هو؟

لا، أنت فقط تؤجل الموضوع.لا يزال الزوجي يعاني من نفس المشكلة، فقط بأعداد أكبر.

@ebel

بالتفكير في الأمر، لديك 64 بت يمثل رقمًا أكبر من 2^64 (double.maxvalue)، لذلك من المتوقع عدم الدقة.

2^64 ليس الحد الأقصى لقيمة مزدوجة.2^64 هو عدد القيم الفريدة التي يمكن أن يحملها النوع المزدوج (أو أي نوع 64 بت آخر). Double.MaxValue يساوي 1.79769313486232e308.

لا يأتي عدم الدقة في أرقام الفاصلة العائمة من تمثيل قيم أكبر من Double.MaxValue (وهذا مستحيل، باستثناء Double.PositiveInfinity).يأتي ذلك من حقيقة أن نطاق القيم المطلوب كبير جدًا بحيث لا يتناسب مع نوع البيانات.لذلك نتخلى عن الدقة مقابل نطاق فعال أكبر.في جوهر الأمر، نحن نسقط أرقامًا كبيرة مقابل نطاق أسي أكبر.

@دكتوربيتزا

ليس حتى؛تستخدم ترميزات IEEE ترميزات متعددة لنفس القيم.على وجه التحديد، يتم تمثيل NaN بواسطة أس جميع البتات-1، ثم أي قيمة غير الصفر للجزء العشري.على هذا النحو، هناك 252 NaNs للزوجي، و223 NaNs للأفراد.

حقيقي.لم أحسب الترميزات المكررة.هناك في الواقع 252-1 NaNs للزوجي و 223-1 NaNs للأفراد.:ص

2^64 ليس الحد الأقصى لقيمة مزدوجة.2^64 هو عدد القيم الفريدة التي يمكن أن يحملها النوع المزدوج (أو أي نوع 64 بت آخر).Double.MaxValue تساوي 1.79769313486232e308.

ليس حتى؛تستخدم ترميزات IEEE ترميزات متعددة لنفس القيم.على وجه التحديد، يتم تمثيل NaN بواسطة الأس all-bit-1، ثم أي قيمة غير صفرية للجزء العشري.على هذا النحو، هناك 252 NaNs للزوجي، 223 NaNs للأفراد.

حقيقي.لم أحسب الترميزات المكررة.يوجد في الواقع 252-1 NaNs للزوجي و223-1 NaNs للأفراد.:ص

دوه، نسيت أن أطرح اللانهايات.

الإصدار التقديري التقريبي لهذه المشكلة الذي تعلمته هو أن العوامات 32 بت تمنحك 5 أرقام من الدقة والعوامات 64 بت تمنحك 15 رقمًا من الدقة.سيختلف هذا بالطبع اعتمادًا على كيفية تشفير العوامات، ولكنها نقطة بداية جيدة جدًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top