ما هي أفضل طريقة لإضافة رقمين بدون استخدام + المشغل ؟

StackOverflow https://stackoverflow.com/questions/365522

  •  21-08-2019
  •  | 
  •  

سؤال

صديق وأنا تسير ذهابا وإيابا مع الدماغ المضايقون وليس لدي أي فكرة عن كيفية حل هذه واحدة.تخميني هو أنه من الممكن مع بعض المعامل المشغلين ، ولكن لست متأكدا.

هل كانت مفيدة؟

المحلول

في C، مع مشغلي المختصة بالبت:

#include<stdio.h>

int add(int x, int y) {
    int a, b;
    do {
        a = x & y;
        b = x ^ y;
        x = a << 1;
        y = b;
    } while (a);
    return b;
}


int main( void ){
    printf( "2 + 3 = %d", add(2,3));
    return 0;
}

وXOR (x ^ y) هو بالإضافة إلى ذلك دون حمل. (x & y) هو ترحيل الخروج من كل بت. (x & y) << 1 هو ترحيل إلى كل الشيء.

وحلقة تبقي إضافة يحمل حتى حمل صفرا لجميع البتات.

نصائح أخرى

int add(int a, int b) {
   const char *c=0;
   return &(&c[a])[b];
}

ولا + أليس كذلك؟

int add(int a, int b) 
{
   return -(-a) - (-b);
}
وظيفة

وإضافة CMS () لجميلة. لا ينبغي أن تلطخت من قبل نفي الأحادية (عملية غير المختصة بالبت، بمثابة باستخدام بالإضافة إلى ذلك: == -y (~ ص) +1). حتى هنا وظيفة الطرح باستخدام نفس تصميم أحادي المعامل الوحيد:

int sub(int x, int y) {
    unsigned a, b;
    do {
        a = ~x & y;
        b =  x ^ y;
        x = b;
        y = a << 1;
    } while (a);
    return b;
}

وتحديد "أفضل". وفيما يلي نسخة الثعبان:

len(range(x)+range(y))

وو+ يؤدي قائمة سلسلة، وليس إضافة.

وحل جافا مع مشغلي المختصة بالبت:

// Recursive solution
public static int addR(int x, int y) {

    if (y == 0) return x;
    int sum = x ^ y; //SUM of two integer is X XOR Y
    int carry = (x & y) << 1;  //CARRY of two integer is X AND Y
    return addR(sum, carry);
}

//Iterative solution
public static int addI(int x, int y) {

    while (y != 0) {
        int carry = (x & y); //CARRY is AND of two bits
        x = x ^ y; //SUM of two bits is X XOR Y
        y = carry << 1; //shifts carry to 1 bit to calculate sum
    }
    return x;
}

والغش. هل يمكن أن ينفي وعدد تطرحه من أول:)

وإذا تعذر ذلك، ابحث عن كيفية عمل الأفعى الثنائية. :)

وتحرير: آه، رأى تعليقك بعد أن نشرت

.

وتفاصيل بالإضافة الثنائية هي هنا .

ملاحظة, هذا من شأنه أن يكون على الأفعى المعروفة باسم تموج حمل الأفعى, الذي يعمل لكن لا أمثل.الثنائية معظم الحيات بنيت في الأجهزة هي شكل من أشكال سريع الأفعى مثل تحمل نظرة إلى الأمام الأفعى.

بلدي تموج حمل الأفعى يعمل لكلا غير موقعة و 2 هو تكملة الأعداد الصحيحة إذا قمت بتعيين carry_in إلى 0 ، 1 تكملة الأعداد الصحيحة إذا carry_in يتم تعيين إلى 1.أود أيضا أن أضيف أعلام لإظهار تجاوز الحد الأدنى أو تجاوز على ذلك.

#define BIT_LEN 32
#define ADD_OK 0
#define ADD_UNDERFLOW 1
#define ADD_OVERFLOW 2

int ripple_add(int a, int b, char carry_in, char* flags) {
    int result = 0;
    int current_bit_position = 0;
    char a_bit = 0, b_bit = 0, result_bit = 0;

    while ((a || b) && current_bit_position < BIT_LEN) {
        a_bit = a & 1;
        b_bit = b & 1;
        result_bit = (a_bit ^ b_bit ^ carry_in);
        result |= result_bit << current_bit_position++;
        carry_in = (a_bit & b_bit) | (a_bit & carry_in) | (b_bit & carry_in);
        a >>= 1;
        b >>= 1;
    }

    if (current_bit_position < BIT_LEN) {
        *flags = ADD_OK;
    }
    else if (a_bit & b_bit & ~result_bit) {
        *flags = ADD_UNDERFLOW;
    }
    else if (~a_bit & ~b_bit & result_bit) {
        *flags = ADD_OVERFLOW;
    }
    else {
        *flags = ADD_OK;
    }

    return result;
}

لماذا لا مجرد incremet الرقم الأول في كثير من الأحيان، والرقم الثاني؟

ووimplememted السبب ضيف في المجمع كما تعليمة واحدة، بدلا من أن تكون بعض مزيج من عمليات أحادي المعامل، هو أنه من الصعب القيام به. لديك ما يدعو للقلق يحمل من معين الترتيب المنخفض قليلا إلى أعلى المقبل من أجل بعض الشيء. هذه هي الاشياء ان تفعل الأجهزة في الأجهزة سريع، ولكن حتى مع C، لا يمكنك أن تفعل في البرنامج بسرعة.

وإضافة اثنين من الأعداد الصحيحة وليس من الصعب، هناك العديد من الأمثلة على إضافة الثنائية عبر الإنترنت.

وهناك مشكلة أكثر صعوبة يعوم أرقام النقطة! هناك مثال على HTTP: //pages.cs .wisc.edu / ~ smoler / x86text / lect.notes / arith.flpt.html

في بيثون باستخدام مشغلي المختصة بالبت:

def sum_no_arithmetic_operators(x,y):
    while True:
        carry = x & y
        x = x ^ y
        y = carry << 1
        if y == 0:
            break
    return x

وكان العمل على هذه المشكلة نفسي في C # و لا يمكن الحصول على كل حالات الاختبار لتمرير. ثم ركضت عبر هذا .

وهنا هو تنفيذ في C # 6:

public int Sum(int a, int b) => b != 0 ? Sum(a ^ b, (a & b) << 1) : a;

ونفذت في نفس الطريقة التي يمكننا فعله بالإضافة الثنائية على الورق.

int add(int x, int y)
{
    int t1_set, t2_set;
    int carry = 0;
    int result = 0;
    int mask = 0x1;

    while (mask != 0) {
        t1_set = x & mask;
        t2_set = y & mask;
        if (carry) {
           if (!t1_set && !t2_set) {
               carry = 0;
               result |= mask;
           } else if (t1_set && t2_set) {
               result |= mask;
           }
        } else {
           if ((t1_set && !t2_set) || (!t1_set && t2_set)) {
                result |= mask;
           } else if (t1_set && t2_set) {
                carry = 1;
           }
        }
        mask <<= 1;
    }
    return (result);
}

ومحسنة لسرعة سيكون أقل ::

int add_better (int x, int y)
{
  int b1_set, b2_set;
  int mask = 0x1;
  int result = 0;
  int carry = 0;

  while (mask != 0) {
      b1_set = x & mask ? 1 : 0;
      b2_set = y & mask ? 1 : 0;
      if ( (b1_set ^ b2_set) ^ carry)
          result |= mask;
      carry = (b1_set &  b2_set) | (b1_set & carry) | (b2_set & carry);
      mask <<= 1;
  }
  return (result);
}

ورأيت هذا الأمر مشكلة 18.1 في مقابلة الترميز. بلدي الثعبان الحل:

def foo(a, b):
"""iterate through a and b, count iteration via a list, check len"""
    x = []
    for i in range(a):
            x.append(a)
    for i in range(b):
            x.append(b)
    print len(x)

وهذه الطريقة يستخدم التكرار، وبالتالي فإن تعقيد الوقت ليس الأمثل. وأعتقد أن أفضل طريقة هي العمل على مستوى أدنى مع العمليات أحادي المعامل.

ومن تنفيذ بلدي على بيثون. أنه يعمل بشكل جيد، عندما نعرف عدد بايت (أو بت).

def summ(a, b):
    #for 4 bytes(or 4*8 bits)
    max_num = 0xFFFFFFFF
    while a != 0:
        a, b = ((a & b) << 1),  (a ^ b)
        if a > max_num:
            b = (b&max_num) 
            break
    return b

ويمكنك القيام بذلك باستخدام بت التحول ووالعملية.

#include <stdio.h>

int main()
{
    unsigned int x = 3, y = 1, sum, carry;
    sum = x ^ y; // Ex - OR x and y
    carry = x & y; // AND x and y
    while (carry != 0) {
        carry = carry << 1; // left shift the carry
        x = sum; // initialize x as sum
        y = carry; // initialize y as carry
        sum = x ^ y; // sum is calculated
        carry = x & y; /* carry is calculated, the loop condition is
                        evaluated and the process is repeated until
                        carry is equal to 0.
                        */
    }
    printf("%d\n", sum); // the program will print 4
    return 0;
}

وسوف الجواب الأكثر صوت لا تعمل إذا كانت المدخلات هي علامة المعاكس. ولكن سوف التالية. لقد خدع في مكان واحد، ولكن فقط للحفاظ على رمز قليلا نظيفة. أي اقتراحات لتحسين ترحيب

def add(x, y):
if (x >= 0 and y >= 0) or (x < 0 and y < 0):
    return _add(x, y)
else:
    return __add(x, y)


def _add(x, y):
if y == 0:
    return x
else:
    return _add((x ^ y), ((x & y) << 1))


def __add(x, y):
if x < 0 < y:
    x = _add(~x, 1)
    if x > y:
        diff = -sub(x, y)
    else:
        diff = sub(y, x)
    return diff
elif y < 0 < x:
    y = _add(~y, 1)
    if y > x:
        diff = -sub(y, x)
    else:
        diff = sub(y, x)
    return diff
else:
    raise ValueError("Invalid Input")


def sub(x, y):
if y > x:
    raise ValueError('y must be less than x')
while y > 0:
    b = ~x & y
    x ^= y
    y = b << 1
return x

إليك الحل القائم على سطر واحد الثلاثي وعودي المحمولة.

int add(int x, int y) {
    return y == 0 ? x : add(x ^ y, (x & y) << 1);
}

ورموز بيثون: (1)

add = lambda a,b : -(-a)-(-b)

وظيفة امدا استخدام مع '-' المشغل

(2)

add= lambda a,b : len(list(map(lambda x:x,(i for i in range(-a,b)))))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top