2013-11-11 3 views
2
int isOverflow(uint a, uint b) { 
     // a and b are unsigned non-zero integers. 
     uint c = a * b; 

     if (c < (a > b ? a : b)) 
       return 1; 
     else 
       return 0; 
} 

Я что-то упустил? Я думаю, что этот фрагмент будет работать.этого условия достаточно для проверки переполнения при умножении

EDIT: Я видел другие решения, такие как multiplication of large numbers, how to catch overflow, который использует некоторые причудливые методы для его проверки. Но мне выше простого решения также выглядит правильно. Вот почему я задаю этот вопрос.

ответ

2

Легко доказать, что это неправильно, находя исключение:

Рассмотрим эти два 8-битных значений без знака: a = 0x1F и b = 0xF.

c = a * b 
c = 0x1F * 0xF 
c = 0xD1    (Overflow! The real answer is 0x1D1) 

c < (a > b ? a : b) 
0xD1 < 0x1F   => False (Wrong!) 

Правильный ответ here.

2

CERT имеет большой документ INT30-C. Ensure that unsigned integer operations do not wrap, который охватывает все случаи целого числа без знака переполнения и проверки они выступают for multiplications требует, чтобы вы проверить, прежде чем выполнить умножение, чтобы предотвратить переполнение прежде, чем это происходит (я изменил пример чтобы соответствовать вашим вопросам):

if (a > SIZE_MAX/b) { 
    /* Handle error condition */ 
} 

c = a * b; 

Это прямо вперед решение вашей проблемы, она была решена, и вы должны использовать решение, которые были доказаны, чтобы работать, придумывая свои собственные решения могут быть склонным к ошибкам.

+0

На многих процессорах умножения более эффективны, чем деления. Я бы подумал, что использование функции для определения того, является ли продукт представимым, было бы чище, чем бросать много целых делений по всему месту. – supercat

Смежные вопросы