Вычитание без знака "минус"

Как я могу вычесть два целых числа в C без оператора -?

Ответ 1

int a = 34;
int b = 50;

Вы можете преобразовать значение b в отрицательное значение с помощью отрицания и добавить 1:

int c = a + (~b + 1);

printf("%d\n", c);

-16

Это два отрицания знака дополнения. Процессор делает это, когда вы используете оператор "-", когда хотите отменить значение или вычесть его.

Преобразование float проще. Просто отрицайте первый бит (shoosh дал вам пример, как это сделать).

EDIT:

Хорошо, ребята. Я сдаюсь. Вот моя независимая от компилятора версия:

#include <stdio.h>

unsigned int adder(unsigned int a, unsigned int b) {
    unsigned int loop = 1;
    unsigned int sum  = 0;
    unsigned int ai, bi, ci;

    while (loop) {
        ai = a & loop;
        bi = b & loop;
        ci = sum & loop;
        sum = sum ^ ai ^ bi;      // add i-th bit of a and b, and add carry bit stored in sum i-th bit
        loop = loop << 1;
        if ((ai&bi)|(ci&ai)|(ci&bi)) sum = sum^loop; // add carry bit
    }

    return sum;
}

unsigned int sub(unsigned int a, unsigned int b) {
    return adder(a, adder(~b, 1));    // add negation + 1 (two complement here)
}


int main() {
    unsigned int a = 35;
    unsigned int b = 40;

    printf("%u - %u = %d\n", a, b, sub(a, b)); // printf function isn't compiler independent here

    return 0;
}

Я использую unsigned int, чтобы любой компилятор обрабатывал его одинаково.

Если вы хотите вычесть отрицательные значения, сделайте так:

 unsgined int negative15 = adder(~15, 1);

Теперь мы полностью независимы от условных условных условных обозначений. В результате моего подхода все ints будут сохранены как два дополнения - поэтому вам нужно быть осторожными с большими ints (они должны начинаться с 0 бит).

Ответ 2

Понтус прав, 2 дополнения не санкционированы стандартом C (даже если это фактический аппаратный стандарт). +1 для творческих ответов Фила; здесь другой подход к получению -1 без использования стандартной библиотеки или оператора.

C задает три возможных представления, поэтому вы можете нюхать, что находится в действии, и получать разные -1 для каждого:

negation= ~1;
if (negation+1==0)                 /* one complement arithmetic */
    minusone= ~1;
else if (negation+2==0)            /* two complement arithmetic */
    minusone= ~0;
else                               /* sign-and-magnitude arithmetic */
    minusone= ~0x7FFFFFFE;

r= a+b*minusone;

Значение 0x7FFFFFFFE будет зависеть от ширины (числа битов значения) целого числа, которое вас интересует; если не указано, у вас есть больше работы, чтобы найти это!

Ответ 3

  • + Нет настройки бита
  • + независимый язык
  • + Может быть настроен для разных типов номеров (int, float и т.д.)
  • - Почти наверняка не ваш домашний ответ на C (который, вероятно, будет о битах)

Разверните a-b:

a-b = a + (-b)
    = a + (-1).b

Производство -1:

float:             pi = asin(1.0);
(with    minusone_flt = sin(3.0/2.0*pi);
math.h)           or  = cos(pi)
                  or  = log10(0.1)
complex: minusone_cpx = (0,1)**2; // i squared
integer: minusone_int = 0; minusone_int--; // or convert one of the floats above

Ответ 4

Учитывая, что целые числа кодирования для поддержки двух дополнений не обязательны в C, повторите итерацию до завершения. Если они хотят, чтобы вы перепрыгнули через пылающие обручи, не нужно быть эффективным!

int subtract(int a, int b)
{
  if ( b < 0 )
    return a+abs(b);
  while (b-- > 0)
    --a;
  return a;
}

Глупый вопрос... возможно, глупое интервью!

Ответ 5

Если вы хотите сделать это для поплавков, начните с положительного числа и измените его бит знака следующим образом:

float f = 3;
*(int*)&f |= 0x80000000;
// now f is -3.
float m = 4 + f; 
// m = 1

Вы также можете сделать это для удвоений, используя соответствующее 64-битное целое число. в visual studio это, например, __int64.

Ответ 6

+ Нет настройки бита + независимый язык + Независимо от типа номера (int, float и т.д.) - Требуется a > b (т.е. положительный результат) - Почти наверняка не ваш домашний ответ на C (который, вероятно, будет о битах)
a - b = c

ограничиваясь числовым пространством 0 <= c < (А + б):

       (a - b) mod(a+b) = c mod(a+b)
a mod(a+b) - b mod(a+b) = c mod(a+b)

упрощение второго члена:

(-b).mod(a+b) = (a+b-b).mod(a+b)
              = a.mod(a+b)

подставляя:

a.mod(a+b) + a.mod(a+b) = c.mod(a+b)
2a.mod(a+b) = c.mod(a+b)

если b > a, тогда b-a > 0, поэтому:

c.mod(a+b) = c
c = 2a.mod(a+b)

Итак, если a всегда больше b, это будет работать.

Ответ 8

Для вычитания в C двух целых чисел вам нужно только:

int subtract(int a, int b)
{
    return a + (~b) + 1;
}

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

Ответ 9

Я полагаю, что это

b - a = ~ (a + ~ b)

Ответ 10

Сборка (аккумулятор):

int result = a;
result -= b;

Ответ 11

Поскольку вопрос задан целыми числами не int s, вы можете реализовать небольшой интерпретатор, чем использовать цифры церкви.

Ответ 12

Создайте таблицу поиска для каждого возможного случая int-int!

Ответ 13

Не тестировалось. Без использования 2-х дополнений:

#include <stdlib.h>
#include <stdio.h>
int sillyNegate(int x) {
   if (x <= 0)
     return abs(x);
   else {
     // setlocale(LC_ALL, "C"); // if necessary.
     char buffer[256];
     snprintf(buffer, 255, "%c%d", 0x2d, x);
     sscanf(buffer, "%d", &x);
     return x;
   }
}

Предполагая, что длина int намного меньше 255, а snprintf/sscanf round-trip не приведет к неуказанному поведению (правильно?)?

Вычитание может быть вычислено с помощью a - b == a + (-b).


Альтернатива:

#include <math.h>
int moreSillyNegate(int x) {
   return x * ilogb(0.5);  // ilogb(0.5) == -1;
}

Ответ 14

Это будет работать с использованием целочисленного переполнения:

#include<limits.h>    
int subtractWithoutMinusSign(int a, int b){
         return a + (b * (INT_MAX + INT_MAX + 1));
}

Это также работает для float (при условии, что вы делаете float-версию...)

Ответ 15

Для максимального диапазона любого типа данных одно дополнение обеспечивает отрицательное значение, уменьшенное на 1 до любого соответствующего значения. например:
~ 1 -------- > -2
~ 2 --------- > -3
и так далее... Я покажу вам это наблюдение, используя небольшой фрагмент кода

#include<stdio.h>
int main()
{
   int a , b;
   a=10;
   b=~a; // b-----> -11    
   printf("%d\n",a+~b+1);// equivalent to a-b
   return 0;
}

Выход: 0
Примечание. Это допустимо только для диапазона типов данных. для типа данных int это правило будет применяться только для значения диапазона [-2,147,483,648 до 2,147,483,647]. Благодарю..... Пусть это поможет тебе.

Ответ 16

        int num1, num2, count = 0;
        Console.WriteLine("Enter two numebrs");
        num1 = int.Parse(Console.ReadLine());
        num2 = int.Parse(Console.ReadLine());
        if (num1 < num2)
        {
            num1 = num1 + num2;
            num2 = num1 - num2;
            num1 = num1 - num2;
        }
        for (; num2 < num1; num2++)
        {
            count++;
        }
        Console.WriteLine("The diferrence is " + count);

Ответ 17

void main()
{
int a=5;
int b=7;

while(b--)a--;
printf("sud=%d",a);

}