Что лучший способ состоит в том, чтобы добавить два числа, не используя + оператор?

Неустранимая ошибка: допустимый размер памяти из XXX байт исчерпан (пытался выделить XXX байты)

Недостаточно памяти для запуска вашего скрипта. PHP достиг предела памяти и перестает его выполнять. Эта ошибка является фатальной, сценарий останавливается. Значение предела памяти можно настроить либо в файле php.ini, либо с помощью ini_set('memory_limit', '128 M'); в скрипте (который перезапишет значение, определенное в php.ini). Цель ограничения памяти заключается в том, чтобы не допустить, чтобы один скрипт PHP собирал всю доступную память и приводил к остановке всего веб-сервера.

Первое, что нужно сделать, это свести к минимуму объем памяти, необходимый вашему сценарию , Например, если вы читаете большой файл в переменной или извлекаете много записей из базы данных и сохраняете их все в массиве, которые могут использовать много памяти. Измените свой код, чтобы вместо этого читать строки по строке или извлекать записи базы данных по одному, не сохраняя их все в памяти. Это требует немного концептуального понимания того, что происходит за кулисами, и когда данные хранятся в памяти и в других местах.

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

Вопросы, относящиеся:

25
задан Jon Seigel 8 July 2010 в 18:55
поделиться

11 ответов

В 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 перенос - в к каждому биту.

цикл продолжает добавлять переносы, пока перенос не является нулем для всех битов.

42
ответ дан phuclv 28 November 2019 в 17:41
поделиться

Добавление двух целых чисел не является настолько трудным; существует много примеров сложения в двоичной системе онлайн.

А более сложной проблемой являются числа с плавающей точкой! Существует пример в http://pages.cs.wisc.edu/~smoler/x86text/lect.notes/arith.flpt.html

1
ответ дан Colin 28 November 2019 в 17:41
поделиться

Причина ADD реализован в ассемблере как единственная инструкция, а не как некоторая комбинация битовых операций, состоит в том, что трудно сделать. Необходимо волноваться о переносах от данного бита низкоуровневого до следующего бита высшего порядка. Это - материал, который машины делают в аппаратных средствах быстро, но что даже с C, Вы не можете сделать в программном обеспечении быстро.

2
ответ дан Jonathan Leffler 28 November 2019 в 17:41
поделиться

Почему не только увеличивают первое число так же часто, как второе число?

2
ответ дан Oliver Friedrich 28 November 2019 в 17:41
поделиться

Отметьте, это было бы для сумматора, известного как сумматор со сквозным переносом , который работает, но не работает оптимально. Большинство двоичных сумматоров, встроенных в аппаратные средства, является формой быстрого сумматора такой как сумматор с ускоренным переносом .

Мой сумматор со сквозным переносом работает и на неподписанный и на 2's дополнительные целые числа при установке carry_in на 0, и 1's дополнительные целые числа, если 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;
}
4
ответ дан phuclv 28 November 2019 в 17:41
поделиться

Обман. Вы могли инвертировать число и вычесть его сначала:)

Сбой, что, ищите, как работает двоичный сумматор.:)

РЕДАКТИРОВАНИЕ: А-ч, видел Ваш комментарий после того, как я отправил.

Детали сложения в двоичной системе здесь .

4
ответ дан Andrew Rollings 28 November 2019 в 17:41
поделиться

Определите "лучше всего". Вот версия Python:

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

Эти + выполняет конкатенацию списка, не дополнение.

5
ответ дан amey91 28 November 2019 в 17:41
поделиться

Нет + право?

int add(int a, int b) 
{
   return -(-a) - (-b);
}
9
ответ дан davidfowl 28 November 2019 в 17:41
поделиться
int add(int a, int b) {
   const char *c=0;
   return &(&c[a])[b];
}
23
ответ дан epoch 28 November 2019 в 17:41
поделиться

Пойдите базирующееся решение

func add(a int, b int) int {

for {
    carry := (a & b) << 1
    a = a ^ b
    b = carry 
    if b == 0 {
        break
    }
}

return a 

}

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

, Например: если мы не будем использовать маску, то мы не получим результат для номеров (-1,1)

def add(a,b):   
    mask = 0xffffffff

    while b & mask:
        carry = a & b
        a = a ^ b
        b = carry << 1

    return (a & mask) if b > mask else a
0
ответ дан 28 November 2019 в 17:41
поделиться

Функция add() в CMS прекрасна. Она не должна быть запятнана унарным отрицанием (небитовая операция, равносильная использованию сложения: -y==(~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;
}
5
ответ дан 28 November 2019 в 17:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: