получить без знака длинное длинное сложение - PullRequest
12 голосов
/ 07 мая 2019

Я хочу получить дополнительный бит добавления двух беззнаковых 64-разрядных целых чисел в c. Я могу использовать x86-64 ASM, если это необходимо. код:

#include <stdio.h>

typedef unsigned long long llu;

int main(void){
  llu a = -1, b = -1;
  int carry = /*carry of a+b*/;
  llu res = a+b;
  printf("a+b = %llu (because addition overflowed), carry bit = %d\n", res, carry);
  return 0;
}

Ответы [ 2 ]

10 голосов
/ 07 мая 2019

Как @EugeneSh.отмечает, что перенос равен 0 или 1. Более того, учитывая, что оба a и b имеют одинаковый тип без знака , их сумма четко определена, даже если арифметический результат превышает диапазон их типа,Более того, результат (C) суммы будет меньше, чем a и b, когда произойдет переполнение, и больше в противном случае, поэтому мы можем использовать тот факт, что реляционные операции C оцениваются либо в 0, либо в 1, чтобы выразить переносбит как

carry = (a + b) < a;

Это не требует каких-либо заголовков и не зависит от конкретной верхней границы или даже от a и b того же типа.Пока оба имеют неподписанные типы, он правильно сообщает о том, переполняет ли сумма более широкий из их типов или unsigned int (в зависимости от того, что шире), что совпадает с их суммой, устанавливающей бит переноса.В качестве бонуса он выражается в терминах самой суммы, которая, я думаю, дает понять, что проверяется.

7 голосов
/ 07 мая 2019

Carry может быть только 0 или 1.1, если произошел обход, и 0 в противном случае.Обтекание происходит в случае, если a + b > ULONG_LONG_MAX верно.Обратите внимание, что это в математических терминах, а не в терминах C, как будто a + b фактически переполнен, тогда это не будет работать.Вместо этого вы хотите изменить его на a > ULONG_LONG_MAX - b.Таким образом, значение переноса будет:

carry = a > ULONG_LONG_MAX - b ? 1 : 0;

или любой другой эквивалентный стиль.

  • Не забудьте включить limits.h.
...