Переповнення безпечного підсумовування


13

Припустимо , що я даюсь фіксованої ширини цілих чисел (тобто вони поміщаються в регістр ширини ш ), 1 , 2 , ... п такі , що їх сума 1 + 2 + + п = S також міститься в регістр ширини w .nwa1,a2,ana1+a2++an=Sw

Мені здається, що ми завжди можемо переставити числа до таким чином, що кожна префіксальна сума S i = b 1 + b 2 + + b i також вписується в регістр ширини w .b1,b2,bnSi=b1+b2++biw

В основному, мотивація полягає у обчисленні суми на машинах реєстрації фіксованої ширини, не турбуючись про цілі переповнення на будь-якому проміжному етапі.S=Sn

Чи є швидкий алгоритм (бажано лінійний час) , щоб знайти таку перестановку (передбачається , дано в якості вхідного масиву)? (або скажіть, якщо така перестановка не існує).ai


3
Наступні дії: Виявлення переповнення підсумовування - чи існує більш швидкий метод, який враховує типові особливості процесора?
Жил "ТАК - перестань бути злим"

1
Просто використовуйте два регістри доповнення та підсумовуйте їх. Навіть якщо він переповнюється посередині, ваша попередня умова гарантує, що переливи скасуються, а результат буде правильним. : P
CodesInChaos

@CodeInChaos: Це дійсно так?
Ар'ябхата

1
Я думаю так. Ви в основному працюють в групі по модулю 2 ^ п, де ви вибираєте канонічне уявлення від -2^(n-1)до 2^(n-1)-1. Звичайно, це вимагає доповнення двох і чітко визначеної поведінки переповнення, але такою мовою, як C #, вона повинна працювати.
CodesInChaos

@CodeInChaos: Чи не існує двох можливостей, які дають однаковий модуль, що залишився ? Ви в основному говорите, незалежно від порядку, один з них ніколи не може відбутися. Або я щось пропускаю? 2n
Ар'ябхата

Відповіді:


10

Стратегія
Наступний алгоритм лінійного часу приймає стратегію зависання навколо , вибираючи або додатні, або негативні числа на основі ознаки часткової суми. Він попередньо обробляє список номерів; він обчислює перестановку вводу на льоту , виконуючи додавання.0

Алгоритм

  1. Partition 1 , ... , п в двох списках, позитивні елементи P і негативні елементи M . Нулі можна відфільтрувати.a1,,anPM
  2. Нехай .Sum=0
  3. Хоча обидва списки не порожні
  4.       Sum>0Sum:=Sum+head(M)M:=tail(M)
  5.       Sum:=Sum+head(P)P:=tail(P)
  6. S

Правильність
Правильність можна встановити, використовуючи прямо індуктивний аргумент про довжину списку чисел.

a1,,an

SumSum=0Sum>0SumSumSum0SumSum

Тепер можна застосувати перший результат, і разом їх достатньо, щоб довести, що сума ніколи не виходить за межі.


0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.