Рисуем многочлен Бернштейна для произвольного числа опорных точек

    Так собственно выглядит рабочая область:


    Можно указать количество точек(от 2 до 13), и перетаскивать любую опорную точку наблюдая в реальном времени как меняется кривая.
    Сделано для себя, с целью разобраться с кривыми разного порядка.
    Базовые знания почерпнуты отсюда:

    Многочлен_Бернштейна
    Биномиальный_коэффициент

    Можно также почитать про кривую Безье, которая является частным случаем многочлена Бернштейна.

    Исходники прилагаются, в архиве также скомпиленный(Win_X86) exe'шник.

    Архив с исходниками и exe'шником.
    Зеркало
    Доработка от Vordigont

    Класс реализующий многочлен откомментирован, разобраться проблемы не будет. Код на шарпе.
    Support the author
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 36

      +1
      Начинать с двух точек много, чтобы разобраться в кривых разного порядка лучше начинать с 1 точки. Так нагляднее. Верхнее ограничение тоже забавно — неужели есть необходимость разбираться с такими сложными кривыми? Если по фану, то сделали бы 100 — красивые штуки хоть получались бы — например развязку в Москве нарисовать можно было бы.
        0
        Я бином делал по простому, через факториал, чтобы переполнение не вызывать ограничил тринадцатью опорными точками. Можно сменить типы в расчетах в исходниках и увеличить количество.
        –3
        
        private int Factorial(int i)
        {
            int ret = 1;
            while (i > 1) ret *= i--;
            return ret;
        }
        

        Красивее так:
        
        private int Factorial(int i)
        {
            if (i == 0) return 1;
            return i * Factorial(i--);
        }
        

        Извините за занудство.
          0
          спорный вопрос. бытует мнение, что несколько выходов (aka return) из функции не есть комильфо, посему через переменную как-то правильнее. тем более ваш вариант с рекурсией, совсем уж извращенство. хочется «красоты», в этом смысле, используйте лямбда выражения :)
            +2
            Ну с несколькими ретурнами — это тема для холиваров. Я чаще встречаю людей, кто так не считает, чем кто так считает. Вроде, это устаревшее мнение, берущее корни из Паскаля в силу определённых нюансов.
              0
              Как мне кажется, функциональное программирование действительно красиво. А лямбда — это еще не ФП. Зато представленный пример с рекурсией как раз «в духе» ФП. И уж никак не извращенство.
                0
                Про рекурсию я негативно отзывался лишь конкретно в данном примере. Сама по себе она не плохая штука.
              +11
              тогда уж:
              private int Factorial(int i)
              {
                  return i == 0 ? 1 : i * Factorial(i-1);
              }
              
                +2
                Соглашусь с вышесказанным, рекурсия для такой простой задачи — как-то не к месту, что ли.

                Зачем усложнять тривиальные вещи? Пожалейте stack :)
                  +2
                  В данном случае вообще нет необходимости считать факториал, можно забить табличку от 0 до 20, 21! уже не влезет в int64.
                    +1
                    Так и сделано, при выборе количества точек биномиальный коэффициент для них вычисляется один раз и заносится в табличку. Откуда при расчетах и берется. Конечно можно совсем статически табличку забить, но это немного усложнит расчет и сделает его менее читабельным, а на производительность не повлияет.
                    0
                    Если среда выполнения поддерживает «хвостовую рекурсию», то stack чувствует себя очень хорошо при подобных вариантах. Да и скорость не хуже.

                    А запись через рекурсию более точно подходит под математическое определение факториала.

                    Так почему бы не записать так, чтоб понятно было даже «доменному специалисту» (в данном случае — математику)? :)
                      0
                      Зачем усложнять тривиальные вещи?

                      Зачем усложнять тривиальные вещи, если можно использовать рекурсию вместо цикла? ;)
                      Имхо, всему своё место.
                    0
                    Написал специально без рекурсии, на случай расширения, чтобы в будущем стек не забивать)
                      0
                      Вот только ваш код не работает.
                        0
                        А подробнее? У меня почему то все работает. Какая ошибка? Алгоритмическая, программная, и где?
                          0
                          Постфиксный декремент.
                          Нужен префиксный:
                          private int Factorial(int i)
                          {
                              if (i == 0) return 1;
                              return i * Factorial(--i);
                          }
                          

                          а еще лучше:
                          private int Factorial(int i)
                          {
                              if (i == 0) return 1;
                              return i * Factorial(i-1);
                          }
                          
                            +1
                            Не посмотрел к какому комменту ваш ответ, подумал про свой код.)
                          0
                          В 4 часа ночи писал. Спасибо Вам за поправку, а остальным — за ценные комментарии. Мне есть еще чему учиться.
                          0
                            0
                            Не нашёл своего варианта с тернарным оператором. Видимо «Lazy Python Programmer».
                            0
                            Ваш вариант не содержит хвостового вызова и потому в языках с его оптимизацией оптимизирован не будет
                            А в .Net (точнее в C#) лучше рекурсию не использовать вовсе, поскольку там нет оптимизации хвостовых вызовов на уровне компилятора. Хотя в CLR инструкция все же присутсвует. Хотя может со времен .NET 3.5 что-то изменилось, честно не в курсе.

                            Хотя применительно в данному примеру это неважно, поскольку здесь не такая большая глубина, чтобы заметить разницу или получить StackOwerflow
                              0
                              Понял я уже, что в 4 утра спать надо, а не умничать. :) С университета просто отложилось в памяти, что факториал считается рекурсивной функцией.
                                0
                                Рекурсией тоже надо уметь правильно пользоваться ;)
                              0
                              private static Int64 Factorial(int n)
                              {
                                  // Due to Int64 limits
                                  if (n > 20)
                                  {
                                      throw new ArgumentException("Factorial parameter can not be greater than 20.", "n");
                                  }
                              
                                  if (n == 0)
                                  {
                                  	return 1;
                                  }
                              	
                                  Int64 result = 1;
                                  for (int i = 1; i <= n; i++)
                                  {
                                      result *= i;
                                  }
                              	
                                  return result;
                              }
                              
                                0
                                Забыл проверку на отрицательные числа.
                                Вообще, если уж считать бином — то лучше бы сделать оптимизации, позволяющие не ограничиваться влезанием полного факториала в разрядную сетку.
                              +3
                              ifolder? Неужели не существует нормальных файл-хостингов?
                                –2
                                Если знаете лучше, дайте линк. ifolder пока не подводил.
                                  +5
                                  Смотреть рекламу и ждать чтобы скачать файл — это нормально? Используйте zalil.ru или rghost.
                                    +1
                                    Довыложил:
                                    zalil.ru/30386914
                                      0
                                      По этой причине я передумал качать файл))
                                      +1
                                      Честно говоря не вижу причины не создать проект на том же code.google.com — сорсы залить в Mercurial, а откомпилинную версию в Downloads

                                      Имхо не намного сложнее чем на всякие файло-помойки, зато возможностей намного больше.
                                        –1
                                        у вас нет дропбокса? а в дропбоксе нету шары?
                                          –1
                                          Нет, более того о дропбоксе и не знал.
                                      +1
                                      Если автор не против, то вот, сделал небольшой «косметический ремонт»
                                        0
                                        Автор совершенно не против и согласен.

                                      Only users with full accounts can post comments. Log in, please.