Русское Крестьянское Умножение

Вот моя короткая реализация Русское Крестьянское Умножение. как это может быть улучшено?

Ограничения: работает только когда a> 0, b> 0

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

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

Lance Roberts 04.11.2008 04:59

@Lance да, вы правы, я это изменю

xxxxxxx 04.11.2008 05:02

Мой положительный отзыв, потому что короткие отступы онлайн МОГУТ быть плохими. Хотя было бы очень приятно читать красивый код с отступами.

temoto 06.03.2009 21:22

spx выглядит так, будто люди тебя ненавидят. я не уверен, почему

Alex Gordon 26.12.2009 01:08

да, люди меня ненавидят, ненавидят только все вокруг. Не знаю почему, может у вас есть ответ? компактный код порождает ненависть, я не могу сказать, что он был дидактическим / поучительным в какой-либо мыслимой форме. намерением очевидным намерением было тщеславие (гореть в аду, я буду). это может быть возможным объяснением той ненависти, о которой вы говорите. Что вы думаете ?

xxxxxxx 31.12.2009 17:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
10 164
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

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

a, b - числа, после цикла for p будет их произведение. там нетрудно читать.

xxxxxxx 04.11.2008 04:23

его труднее читать, чем нужно, и человек, который его написал, не тот человек, который может судить, трудно ли это читать. Что плохого в добавлении нескольких переносов строк?

Airsource Ltd 04.11.2008 04:24

добавление переносов строк нарушает компактность :)

xxxxxxx 04.11.2008 04:30

вы имеете в виду "добавление переносов строк делает нечитаемым". Не меняет скомпилированный размер.

Airsource Ltd 04.11.2008 04:32

Почему бы вам просто не написать на ассемблере и перестать возиться с этими игровыми языками, такими как C. Вы, очевидно, выдающийся программист, и вам, вероятно, следует заняться преподаванием или консультированием.

Tim 04.11.2008 04:53

p не инициализирован.

Что произойдет, если a равен нулю?

Что произойдет, если a отрицательный?

Обновлять: Я вижу, что вы обновили вопрос, чтобы решить вышеупомянутые проблемы. Хотя теперь ваш код работает так, как указано (за исключением проблемы переполнения), он все еще менее читабелен, чем должен быть.

p должен быть инициализирован с умножением 0, здесь работает только для a> 0, b> 0 :) спасибо за вопрос

xxxxxxx 04.11.2008 04:28

Я думаю это ужасно Это точно такой же код с точки зрения компилятора и (надеюсь) намного более понятный

int sum = 0;
while(1)
{
    sum += (a & 1) * b;
    if (a == 1)
       break;

    a = a / 2;
    b = b * 2;
}

И вот уже выписал, понимаю.

да, это была моя первая реализация :) потом вспомнил некоторые хитрости :)

xxxxxxx 04.11.2008 04:31

Надеюсь, мне никогда не придется писать с вами код. Я не понимаю, почему кто-то мог взять что-то подобное вышеупомянутому и произвести то, что есть у вас, если только они не предприняли полубезнадежную попытку записи конкурса «Обфусцированный C». : |

Rob Howard 04.11.2008 04:41

Роб, задним числом это очевидно, но я действительно думал, что ты с самого начала говоришь со мной, а не с spx2!

Airsource Ltd 04.11.2008 04:46

Я бы подумал, что сдвиг бит будет быстрее, чем деление или умножение, и я не уверен, что все компиляторы будут делать это таким образом. (Хотя могут, здесь не уверен).

Lance Roberts 04.11.2008 04:58

битовый сдвиг происходит быстрее, чем умножение или деление, НО любой достойный компилятор оптимизирует умножение на константу в набор битовых сдвигов, если это вообще возможно. Единственный компилятор, с которым я столкнулся, который этого не сделал, - это компилятор IAR H8. Я подозреваю, что это не целевая платформа.

Airsource Ltd 04.11.2008 06:17

Эй, пока вы занимаетесь этим, почему вы не заменили a & 1 на a % 2? И почему бы также не заменить sum += ... на sum = sum + ...? Я имею в виду, просто чтобы сделать это ДЕЙСТВИТЕЛЬНО ужасным. Эй, если кто-то не умеет читать C, ему следует искать работу VB. ;)

vladr 09.03.2010 20:31

Влад - Я тоже умею читать по-английски, но это не значит, что я предпочитаю читать это так.

Airsource Ltd 16.03.2010 15:23

В цикле еще есть умножение. Если вы хотите снизить стоимость умножения, вы можете использовать вместо этого:

for(p=0;p+=(-(a&1))&b,a!=1;a>>=1,b<<=1);

да, это правда мой друг, фантастика! спасибо :) но ограничение b> 0 спасло вас здесь, если бы не это, вы были бы неправы.

xxxxxxx 04.11.2008 04:42

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

int RussianPeasant(int a, int b)
{
    // sum = a * b
    int sum = 0;
    while (a != 0)
    {
        if ((a & 1) != 0)
            sum += b;
        b <<= 1;
        a >>= 1;
    }
    return sum;
}
Ответ принят как подходящий

Его можно улучшить, добавив пробелы, правильные отступы и правильное тело функции:

int peasant_mult (int a, int b) {
  for (p = 0;
       p += (a & 1) * b, a != 1;
       a /= 2, b *= 2);
  return p;}

Видеть? Теперь понятно, как используются три части объявления for. Помните, что программы написаны в основном для человеческого глаза. Нечитаемый код - это всегда плохой код.

А теперь, для моего личного развлечения, хвостовая рекурсивная версия:

(defun peasant-mult (a b &optional (sum 0))
  "returns the product of a and b,
   achieved by peasant multiplication."
  (if (= a 1)
      (+ b sum)
      (peasant-mult (floor (/ a 2))
                    (* b 2)
                    (+ sum (* b (logand a 1))))))

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

// Russian Peasant Multiplication ( p <- a*b, only works when a>0, b>0 )
// See http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
for( p=0; p+=(a&1)*b, a!=1; a>>=1,b<<=1 );

Есть действительно простой способ улучшить это:

p = a * b;

У него даже есть то преимущество, что a или b могут быть меньше 0.

Если вы посмотрите, как это работает на самом деле, вы увидите, что это просто обычное ручное умножение, выполняемое в двоичном виде. Ваш компьютер делает это внутренне таким образом (1), поэтому самый простой способ использовать русский крестьянский метод - использовать встроенное умножение.

(1) Возможно, у него более сложный алгоритм, но в принципе вы можете сказать, что он работает с этим алгоритмом.

Ответ без умножения и деления:

function RPM(int a, int b){
    int rtn;
    for(rtn=0;rtn+=(a&1)*b,a!=1;a>>=1,b<<=1);
    return rtn;
}

err ... (a & 1) * b ЯВЛЯЕТСЯ умножение. :)

vladr 09.03.2010 20:36

Другие вопросы по теме