أسئلة في التدفق على العوامات والطفرات × الأعداد الصحيحة

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

سؤال

1) هل هذا غير قابل للتدفق؟

long long v1, v2, result;
[..]
result = ((long double) v1 / v2) * 1000000LL;

1.A) هل يمكنني ترك LL على الثابت؟ و لماذا.

2) بدلاً من ذلك ، هل هذا الاختلاف بدون تعويم موافق؟

long long l1, l2, result;
[..]
result = (1000000 * (v1 / v2) + v1 % v2);

2. أ) التي لديها المزيد من النفقات العامة؟ الأول أو هذا المثال؟

3) هل يمكن أن تفيض في التدفق ، أو مجرد التفاف إلى قيم "عاقلة"؟

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

المحلول

نعم ، يمكن أن تفيض النتيجة في المثال (1) بسهولة إذا ، على سبيل المثال ، V1 = 1000000000000000 و V2 = 1. لا تحتاج إلى LL على هذا الثابت int (تحت معظم التطبيقات ، على أي حال).

(2) يمكن أن يفيض التدفق تمامًا وكذلك المثال 1 إذا كان V1 و V2 كما أعطيتهما.

المثال الأول أكثر تكلفة لأن الحساب النقطة العائمة هو الأكثر تكلفة من الحساب الصحيح.

(3) قد تتفوق العوامات بالتأكيد والنتائج التي تعتمد على التنفيذ.

كما أشار Arjit ، يمكنك منع التدفق من خلال التحقق من قيمة V1 قبل إجراء الحساب. إذا كان V1 سالبًا ، فستحتاج أيضًا إلى التحقق من الإصدار السلبي ، وربما يكون ما يلي أفضل ...

if ((LONG_LONG_MAX / 1000000) > V1)
{
...
}

إذا كنت بالفعل ضد الحد الأقصى ، فيمكنك أن تمنح نفسك مساحة أكبر قليلاً من خلال إعلان المتغيرات unsigned.

لاحقًا - تحرير لتصحيح الخطأ الذي أشار إليه أرجيت.

نصائح أخرى

أولاً

  1. إذا كان القيام بذلك أو حساب طويل لا ينطوي على تعويمه. لأن نتيجتك في الجزء الأول سيكون لها العديد من القيم المختلفة التي تكاد تكون متساوية.

لأن (تعويم) v1/v2 = ab.cdef. // حيث يمكن أن تختلف CDEF.

يمكن أن يتسبب تنفيذك الثاني أيضًا في التدفق إذا كان V1 = 2^15 و V2 = 1

لذلك إذا كنت تبحث عن الفائض والأمان ، فيجب عليك التحقق دائمًا

مثل 2^18/ثابت وهو 1000000 في هذه الحالة

لذا

if(2^18/Constant > v1)

    result = (1000000 * (v1 / v2) + v1 % v2);

سيكون هذا أي دليل على الاختراق.

أتمنى أن يساعدك هذا

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