أسئلة في التدفق على العوامات والطفرات × الأعداد الصحيحة
-
27-09-2019 - |
سؤال
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
.
لاحقًا - تحرير لتصحيح الخطأ الذي أشار إليه أرجيت.
نصائح أخرى
أولاً
- إذا كان القيام بذلك أو حساب طويل لا ينطوي على تعويمه. لأن نتيجتك في الجزء الأول سيكون لها العديد من القيم المختلفة التي تكاد تكون متساوية.
لأن (تعويم) v1/v2 = ab.cdef. // حيث يمكن أن تختلف CDEF.
يمكن أن يتسبب تنفيذك الثاني أيضًا في التدفق إذا كان V1 = 2^15 و V2 = 1
لذلك إذا كنت تبحث عن الفائض والأمان ، فيجب عليك التحقق دائمًا
مثل 2^18/ثابت وهو 1000000 في هذه الحالة
لذا
if(2^18/Constant > v1)
result = (1000000 * (v1 / v2) + v1 % v2);
سيكون هذا أي دليل على الاختراق.
أتمنى أن يساعدك هذا