эффективность
От: фонарь Беларусь блог
Дата: 14.11.03 15:08
Оценка:
что можно сказать по поводу такого алгоритма
a -= b;   
b += a;   
a = b - a;

против обычной замены?
Re: эффективность
От: Vasili Trifonov Беларусь  
Дата: 14.11.03 15:15
Оценка:
Здравствуйте, фонарь, Вы писали:

Ф>что можно сказать по поводу такого алгоритма

Ф>
Ф>a -= b;   
Ф>b += a;   
Ф>a = b - a;
Ф>

Ф>против обычной замены?

как насчет переполнения?

Regards,
Vasili
Re: эффективность
От: Аноним  
Дата: 14.11.03 17:08
Оценка:
Здравствуйте, фонарь, Вы писали:

Ф>что можно сказать по поводу такого алгоритма

Ф>
Ф>a -= b;   
Ф>b += a;   
Ф>a = b - a;
Ф>

Ф>против обычной замены?

А самому проверить слабо...
У меня, например, твой вариант в 2.5 раза медленнее варианта с промежуточной переменной.

Плюс что за эффективность тебя интересует?
По памяти твой вариант эффективнее, а по скорости явно нет
Re[2]: эффективность
От: Gaperton http://gaperton.livejournal.com
Дата: 14.11.03 19:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, фонарь, Вы писали:


Ф>>что можно сказать по поводу такого алгоритма

Ф>>
Ф>>a -= b;   
Ф>>b += a;   
Ф>>a = b - a;
Ф>>

Ф>>против обычной замены?

А>А самому проверить слабо...

А>У меня, например, твой вариант в 2.5 раза медленнее варианта с промежуточной переменной.

А>Плюс что за эффективность тебя интересует?

А>По памяти твой вариант эффективнее, а по скорости явно нет
Все равно в варианте с промежуточной переменной компилятор применит регистровую оптимизацию, записи в память не будет (что и показывает тест). Так что в таких трюках нет надобности.
Re: эффективность
От: Кодт Россия  
Дата: 16.11.03 11:15
Оценка:
Здравствуйте, фонарь, Вы писали:

Ф>что можно сказать по поводу такого алгоритма

Ф>
Ф>a -= b;   
Ф>b += a;   
Ф>a = b - a;
Ф>

Ф>против обычной замены?

Поскольку у Intel x86 нет операций память-память, за исключением строковых (movsb и т.п.), то по-любому возникнет потребность в промежуточном регистре.

extern void swap1(unsigned int& a, unsigned int& b)
{
  unsigned int x = a;
  a = b;
  b = x;

  // реконструкция ассемблерного кода (*1*)
  unsigned int x = a; // *2*
  unsigned int y = b;
  a = y;
  b = x;
}

extern void swap2(unsigned int& a, unsigned int& b)
{
  a -= b;
  b += a;
  a -= b;

  // реконструкция
  unsigned int x = a;
  unsigned int y = b;
  x -= y;
  a = x; // *3*
  y += x;
  b = y;
  x -= y;
  a = x;
}

extern unsigned int p = 100, q = 200;

int main()
{
  swap1(p,q);
  swap2(p,q);
  
  return 0;
}

*1* — получить ассемблерный код можно, запустив cl -Ox -Fa test.cpp
(-Ox — оптимизировать все).
Реконструировал вручную. Все-таки С выразительнее ассемблера

*2* — x,y — регистры. В ассемблерном листинге видно, что требуются 4 регистра: адрес a, адрес b (переданные параметры), x, y. Поскольку конвенция предполагает несохранение только трех — eax,ecx,edx, то четвертый — esi — сохраняется в стеке (push esi / pop esi).

*3* — не знаю, зачем пишется промежуточное значение a. Без этой строки вполне можно обойтись. Тем не менее...

Итого
* swap1 имеет 2 чтения и 2 записи в память.
* swap2 — 2 чтения, 3(2) записи и 3 арифметических операции регистр-регистр.
* Если бы swap2 использовал арифметику память-регистр, то ему пришлось бы неоднократно читать значения из памяти (что там получилось?). Естественно, это было бы еще медленнее.
Перекуём баги на фичи!
Re[2]: эффективность
От: kepo4ka  
Дата: 17.11.03 21:50
Оценка:
Здравствуйте, Кодт, вы тут много всего написали:

Насколько я понимаю применять такой алгоритм в принципе не стоит. Равно как и оценивать его эффективность.
Если переменная a и b, не целочисленные. И a намного больше b => a-=b даст нам a. И весь алгоритм посыпался.
Re[3]: эффективность
От: Кодт Россия  
Дата: 18.11.03 09:36
Оценка: 38 (3) +1
Здравствуйте, kepo4ka, Вы писали:

K>Здравствуйте, Кодт, вы тут много всего написали:


K>Насколько я понимаю применять такой алгоритм в принципе не стоит. Равно как и оценивать его эффективность.

K>Если переменная a и b, не целочисленные. И a намного больше b => a-=b даст нам a. И весь алгоритм посыпался.

Потому что плавающие числа конечной разрядности не образуют группу ни по сложению, ни по умножению.
А фиксированные — образуют группу (целые — образуют даже кольцо — вычетов по модулю 2^n).

А еще они образуют группу по битовому сложению (xor). Отсюда — такая формула
a = a (-) b;
b = a (+) b;
a = a (-) b;

где (+), (-) это операция над группой и ее противоположность.
Общедоступны 3 варианта: +|-, -|+ (sic! обратите внимание на расположение операндов -- здесь нет коммутативности) и ^|^.

Абстрактная алгебра рулит!
Перекуём баги на фичи!
Re[4]: эффективность
От: фонарь Беларусь блог
Дата: 19.11.03 08:47
Оценка:
Здравствуйте, Кодт, Вы писали:

К>А еще они образуют группу по битовому сложению (xor). Отсюда — такая формула

К>
К>a = a (-) b;
К>b = a (+) b;
К>a = a (-) b;
К>


К>Абстрактная алгебра рулит!



фнтастика! как раз только хотел вынести на суд такой вариант
a ^= b;
b ^= a;
a ^= b;

тут уж эффективность так эффективность
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.