1. C++ / Говнокод #5023

    +167

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    T toPower(T base, int exponent)
    {
    	//cout << "++++++++Start template+++++++++++++" << endl;
    	T result = base;
    	if(exponent == 0) return (T)1;
    	if(exponent < 0) return (T)0;
    
    	while(--exponent)
    		result *= base;
    	//cout << "++++++++Finish template++++++++++++" << endl;
    	return result;
    }

    Запостил: 1_and_0, 22 Декабря 2010

    Комментарии (30) RSS

    • Отрицательная степень? Дробные числа? Это фантастика!
      Ответить
      • Не совсем понял вопросов. Что вы фантастического видите в отрицательных степенях?
        Здесь это не реализовано, а через логарифм и экспоненту очень даже неплохо работается с отрицательной степенью.
        Ответить
        • Вы лишены чувства юмора? Неужели непонятно, что сказал rat4 или надо было использовать http://www.w3.org/TR/emotionml/ ?
          Фантастикой программа считает отрицательные степени. Кто мешал забабахать ветку:
          if(exponent < 0) 
          	while(++exponent)
          		result /= base;
          ?
          Ответить
          • болею..., простуда - враг программиста, совсем не до юмора(
            Ответить
            • Тогда другое дело. Выздоравливайте!
              Ответить
            • Кхм...
              [offpost]
              Можно ли считать себя простуженным, если в магазине говоришь: "Дайте мне Ява Скрипт Золотую, крепкую, пожалуйста"... ?
              [/offpost]
              Ответить
    • while(--exponent)
      		result *= base;
      Может это метод повышения точности вычислений?

      Или код написан для какого-нибудь микроконтроллера, который возведение в степень не поддерживает?
      Ответить
      • Этот метод корректно возводит отрицательные числа. Хотя для них можно было посчитать экспоненту логарифма модуля, а знак определить по чётности показателя.
        Ответить
    • Так а в чем вы здесь видите проблему? Алгоритм, разумеется, не оптимальный - по уму надо было бы реализовывать Russian Peasant Algorithm. Но для студенеческого кода или для временной заглушки - вполне потянет.

      Про "возведение в степень не поддерживает" - мимо кассы. Никакой из современных мэйнстриморвых процессоров практичное возведение в степень не поддерживает. Есть, разумеется, билиотечная `pow` и аналогичная поддержка в системе процессорных команд - но это обобщенное плавающее экспоненциирование, за которое надо сразу бить по рукам, особенно в целочисленном коде.

      Я бы предположил, что приведенная функция написана именно для целочисленного возведения в степень (и именно так это и делается на практике - написанием своей функции), но представленный вариант задуман в качестве работоспособной "заглушки", т.е. Russian Peasant решили реализовать потом, когда/если руки дойдут.
      Ответить
      • Все верно, но какое отношение к возведению в степень относится алгоритм умножения Russian Peasant Multiplication?
        Ответить
        • Это такая мнемоническая "утка". Алгоритм умножения, в итоге, основан на разложении числа в двоичной системе. Собственно такая же процедура предлагается для возведения в степень.
          Не нужно постоянно перемножать само число, а можно работать с его уже вычисленными на предыдущих шагах степенями. Как-то так.

          В общем, как писал Макконел: "Не оптимизируй". :-)
          Ответить
          • Я понял, о чем Вы.
            Впрочем, думается мне, что возвести во вторую степень(это является намного более частым случаем) - будет быстрее через: a*a, чем через этот алгоритм.
            Ответить
            • Этот алгоритм всегда выполняет не больше умножений, чем прямой процесс. Насколько я понимаю, даже логорифм двоичный от степени.
              Он в Кнуте описан должен быть.
              Ответить
              • .
                Ответить
              • я бы написал так
                int pow (int a, int k)
                {
                if (k==0) return 1;
                if (k==1) return a;
                if (k&1) return a*pow(a,k-1);
                int r = pow(a,k>>1);
                return r*r;
                }
                Ответить
            • Вот если действительно часто приходится перемножать то, что дорого стоит, скажем нужно возводить в степень матрицы (я не знаю... Там.. Для получения состояния в цепях безусловного перехода или вычислять предел цепей Маркова), то, вероятно, стоит применять такой вот алгоритм оптимизации сокращающий дорогостоящее перемножение, да.
              Ответить
        • Возведение в степень, по определению, есть многократное умножение. Вот здесь

          http://lafstern.org/matt/col3.pdf

          почитайте классическую статью классического автора том, как Russian Peasant используется для возведения в степень.
          Ответить
          • Russian Peasant — это про двоичное представление показателя и про оптимизацию возведения в степень через возведение в квадрат, в четвёртую, восьмую и т. д. степень?
            Ответить
    • Совершенно ненужный велосипедизм.
      Ответить
      • А как нужно? Найти готовую библиотеку?
        Ответить
        • Зачем искать? Она есть и тем более стандартная. <cmath>
          Ответить
          • Там только для плавающих чисел в base. Зачем лишние преобразования, потери скорости и точности?
            Ответить
          • Там же шаблон.
            В него можно и матрицы подсунуть :-) И вообще какие-нибудь причудливые объекты, которые перегрузили умножение.
            Ответить
            • Я про стандартную библиотеку <cmath>. Там вроде все числа с плавающей точкой типа float и double.

              http://www.cplusplus.com/reference/clibrary/cmath/pow/

              Или у Вас какой-то не стандартный компилятор?
              Ответить
              • Видимо я недостаточно точно выразился.
                "Там" означает в говнокоде.
                В говнокоде шаблон. Он может быть инстанцирован для любой сущности реализующей умножение.
                Ответить
                • Тип T есть, а шаблона нет. :-) Комментарии не в счет. Для оптимизации может быть и есть смысл, но как выше было сказано: "не оптимизируй". К тому же "оптимизация" не оптимальная.
                  Ответить
                  • Со всем согласен. :-)
                    Просто... Направление мысли автора угадывается. Хотелось "оптимально" перемножать всё...

                    Хотелось как лучше, а получился ...
                    Ответить
    • Шаблоны всех языков, кроме моего, негодуют!
      Ответить

    Добавить комментарий