سؤال

وجود مشكلة صغيرة هنا على رمز تكاثر المصفوفة. يبدو أنني أفقد الدقة على مضاعفات المصفوفات الكبيرة (يتم تشغيل الكود الخاص بي بشكل جيد على المصفوفات الصغيرة).

حلقت بلدي هي ما يلي:

for (int j = 0; j < columns; j++)
{
    float[] column = otherMatrix.Column(j);
    for (int i = 0; i < rows; i++)
    {
        double s = 0;
        for (int k = 0; k < size; k++)
            s += this[i,k] * ((double) column[k]);
        result[i, j] = (float)s;
    }
}

كما ترون ، أجبر دقة (مزدوجة) للتأكد من أنني لا أفقد الدقة عند ضرب عوامتي.

بالنظر إلى رمز IL ، يمكنني أن أرى اثنين من Conv.R8 مما يجعلني أعتقد أن رمز IL لديه هذا التحويل الدقيق إلى الدقة.

ومع ذلك ، عند تشغيله وإلقاء نظرة على التفكيك (آلة x86) ، أرى ما يلي:

0000024e  fld         dword ptr [edx+eax*4+8] 
00000252  fmulp       st(1),st 
00000254  fadd        qword ptr [ebp-64h] 
00000257  fstp        qword ptr [ebp-20h] 

يجعلني أعتقد أن JIT اعتقدت أنه نظرًا لأنني أتضاعف بالفعل العوامات ، فإنه لا ينبغي أن يستخدم الضرب الدقيق المزدوج ولكن الضرب الدقيق الفردي ، مما يمنحني الأخطاء التي كنت أتتبعها.

هل انا على حق ؟ هل هناك أي طريقة لإجبار هذا الضرب الدقة المزدوجة؟

شكرًا

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

المحلول

أنا فكر في أنت تسيء تفسير التجميع. أعتقد أن FMULP تعمل دائمًا على سجلات 80 بت. سأفاجأ برؤية JIT يفعل الشيء الخطأ هنا.

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

نصائح أخرى

قد ترغب في التبديل إلى عشري لدقة أفضل

أولاً ، هل هناك أي سبب لا يمكنك استخدامه العشري؟ تحافظ العشرية على الدقة اللازمة لأي رقم ، وليس لديها "أقرب تمثيل ثنائي للمشكلات المانتيسا" التي يمكن أن تؤدي إلى XY = Z +- .0000000000 ... 0000001.

من MSDN:

يمثل نوع القيمة العشرية أعدادًا عشرية تتراوح من 79،228،162،514،264،337،593،543،950،335 إلى 79،228،162،514،264،337،593،543،950،335. يعد نوع القيمة العشرية مناسبًا للحسابات المالية التي تتطلب أعدادًا كبيرة من الأرقام المتكاملة والتكسرية الهامة ولا توجد أخطاء حول التشغيل. النوع العشري لا يلغي الحاجة إلى التقريب. بدلا من ذلك ، فإنه يقلل من الأخطاء بسبب التقريب.

إذا فشل هذا ، حاول إلقاء الجانبين للمضاعفة قبل الضرب. قد يؤدي تعويم * مزدوج إلى مضاعفة ، ولكن نظرًا لأن مزدوجك هو تعويم في مقارنة مع تعويم آخر ، فقد يكون المترجم يتجاهل دقتك المطلوبة ، "مع العلم" أن اثنين من العوامات لن تجعل مضاعفة.

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