Гамма-функция и факториал: вычислительные вопросы

Тема в разделе "Кухня", создана пользователем Pia, 19 окт 2008.

  1. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Вообще, я нашёл, что гамма-функция вычисляется точно так же формулой Стирлинга с той лишь разницей, что одни коэффицент не умножается, а делится.
  2. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    <......Тяжелый вздох.....>
    Клиника :(
    P.S
    Ну сказано же - Г(n+1) = n!
  3. Муркенштейн Гастролёр

    • Участник
    Рег.:
    20.02.2006
    Сообщения:
    1.794
    Симпатии:
    15
    Репутация:
    2
    Адрес:
    Nowhere
    Оффлайн
    Pia, гамма-функция действительно является обобщением факториала (говоря простым языком, "одно и то же"), и это действительно можно доказать. Попробуйте всё же почитать книги по матанализу.
  4. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Это только для целых чисел. Ну сколько раз можно повторять?!
    Г(-0.5+1)<>-0.5! что легко проверить.
    Ну и что толку? Формула нахождения гамма-функции ни чуть не точнее, и как перевести результат гамма-функции в факториал мы не знаем.
  5. NS Нефёдов Сергей

    • Заслуженный
    • Ветеран
    • Старожил
    Рег.:
    02.05.2006
    Сообщения:
    6.811
    Симпатии:
    96
    Репутация:
    3
    Адрес:
    Санкт-Петербург
    Оффлайн
    Факториал определен только для целых неотрицательных! Как он может вне области своего определения давать значения?
  6. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    Да ужжж.
    P.S
    Ну сказано же - Г(n+1) = n!

    P.P.S я чуть дополню, во избежание :)
    - Формула Г(n+1) = n! для целых чисел. Нецелого факториала нет. Есть Гамма-функция.
    В общем случае Г(z+1) = z*Г(z) -т.е обобщение факториала.

    Вы можете придумать любую другую функцию, которая совпадает с факториалом при целых значениях и быть абсолютно другой в нецелых, но это из серии про неуловимого Джо.
    Коли первое утверждение неверно, выводы и смотреть не стоит.
    Г(0.5)=sqrt(pi) а не 0.886. Г(0.5) это не 0.5!
    То что считает виндовый калькулятор n! - это Г(n+1)
    0.5!=Г(0.5+1)=Г(0.5)*0.5=sqrt(pi)*0.5
    Г(0.5)=Г(-0.5+1)=-0.5*Г(-0.5) т.е Г(-0.5)= -2*sqrt(pi)

    См. выше про значения.
    Типа на калькуляторе (-0.5!) это Г(0.5) т.е sqrt(pi)

    И уж не стоит Вам сейчас соваться в отрицательные или комплексные значения.
    Там все хуже.
    Хотя мне любопытно, сколько Вам покажет Ваша программа при n=-1 или -2,-3 и т.д. :)
  7. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    Мы знаем :) Вы не знаете.
  8. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Вообще-то, да, Г(n+1)=n! и для нецелых - я проверил своей программой. Спасибо, Vladimirovich.
    И что толку? Вы игнорирует тот факт, что у нас нет формулы вычисления гамма-функции. Та, что у меня есть, не более точна. Это по-сути одна и та же.

    Факториалы нецелых чисел нужны, например, для статистического описания нейросетевых преобразователей биометрия/код ключа доступа биномиальным законом распределения зависмимых биометрических данных, и много где ещё.
  9. drowsy Учаcтник

    • Участник
    Рег.:
    08.09.2006
    Сообщения:
    1.282
    Симпатии:
    1
    Репутация:
    0
    Адрес:
    Toronto, Canada
    Оффлайн
    Это вы игнорируете то, что вам пишут. Я вам три разных формулы приводил, всё не в прок.
  10. EgisLT Учаcтник

    • Участник
    Рег.:
    14.12.2007
    Сообщения:
    431
    Симпатии:
    12
    Репутация:
    0
    Оффлайн
    Как он определяется?
  11. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Все три - модификация формулы Стирлинга, которую я и использую. Если бы мне знать больше чисел ряда Стирлига, алгоритм был бы точнее.
    Вычисляется - похоже, что только нажатием кнопок на калькуляторе Windows. Для очень больших - формулой Стирлинга, которую я использую с алгоритме программы.
  12. EgisLT Учаcтник

    • Участник
    Рег.:
    14.12.2007
    Сообщения:
    431
    Симпатии:
    12
    Репутация:
    0
    Оффлайн
    Wiki пишет

    The factorial function can also be defined for non-integer values, but this requires more advanced tools from mathematical analysis. The function that "fills in" the values of the factorial between the integers is called the Gamma function, denoted Γ(z) for integers z no less than 1, defined by... http://en.wikipedia.org/wiki/Factorial

    Kак я понимаю это, что для х! (х real) нужно пользаватся определением Гамма функ.
  13. drowsy Учаcтник

    • Участник
    Рег.:
    08.09.2006
    Сообщения:
    1.282
    Симпатии:
    1
    Репутация:
    0
    Адрес:
    Toronto, Canada
    Оффлайн
    В том-то и дело, что модификации. Там у рядов другие коэффициенты совсем, один расходящийся, другой сходящийся, параметр есть, можно точность выбрать. Тонкостей достаточно.
  14. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Ещё раз внимательней посмотрел. Вот это кажется убедительным!!!
    [​IMG]
  15. gennah Учаcтник

    • Участник
    Рег.:
    04.10.2007
    Сообщения:
    474
    Симпатии:
    1
    Репутация:
    1
    Оффлайн
    Pia, а вы попробуйте вашу программу... продать! :) Думаю, это прорыв - не иначе, и желающих найдётся пруд пруди.
  16. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Да, и получить Нобелевскую премию по математике. Жаль, что такой нет.
  17. Муркенштейн Гастролёр

    • Участник
    Рег.:
    20.02.2006
    Сообщения:
    1.794
    Симпатии:
    15
    Репутация:
    2
    Адрес:
    Nowhere
    Оффлайн
    Это Вы откуда скопипастили? Вы сами можете объяснить вышенаписанное?
  18. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Какая разница?
  19. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    :D Хороший ответ

    Разница в том, что понятие факториала нецелых чисел в математике отсутствует.
    Гугл на первое место по поиску "Факториалы нецелых чисел" ставит теперь данный форум :)

    А отсутствует, потому что они никому не нужны :) Есть Гамма функция.

    2 Муркенштейн
    Это Pia скопипастил из (о доверии к ресурсу сейчас не будем)
    http://www.wikiznanie.ru/ru-wz/index.php/Факториал_дробного_числа
    причем совершенно не обратив внимание на
    "Вычисляемое таким способом значение факториала дробного числа является приближенным. Для точных расчетов необходимо использовать гамма-функцию."
  20. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Ну так я для расчёта факториалов использовал модифицированну формулу гамма-функции.
    Какие у кого проблемы?
    Неправда. У меня есть (был) справочник по математике для учащихся ВУЗов, там даётся формула Стирлинга с описанием, как сейчас помню, "Факториалы больших чисел могут быть выражены приближённо формулой Стирлинга. Эта формула имеет место и не при целом n".
  21. Муркенштейн Гастролёр

    • Участник
    Рег.:
    20.02.2006
    Сообщения:
    1.794
    Симпатии:
    15
    Репутация:
    2
    Адрес:
    Nowhere
    Оффлайн
    Всё понятно. "Волны перекатывались через мол и падали вниз стремительным домкратом" ©
  22. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    Правда.
    Формула имеет место быть, а не факториалы.
    Она ессно имеет смысл для Гамма функции.
    Внимательно читаем
    http://en.wikipedia.org/wiki/Gamma_function
    и связанную
    http://en.wikipedia.org/wiki/Stirling's_approximation
    Заодно и в образовательных целях полезно будет
  23. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    [​IMG]
    Последняя формула даёт результат даже для небольших нецелых чисел z. Так факториал можно вычислить даже для отрицательных величин. Но совсем не быстро и всего до 8 значимых знаков.
    ————————————————
    {$N+}

    const
    d=1000000; { Уменьшить для большей частоты вывода на экран состояния }
    l=100000000; { Увеличить для большей точности вычисления }

    var
    C,z,r1,r2:extended;
    n,d1:longint;

    begin
    C:=-0.57721566490153286060651209008240243104215933593992;
    repeat
    readln(z);
    z:=z+1;
    r1:=1/(1+z/1)*exp(z/1);
    d1:=d;
    for n:=2 to l do
    begin
    r1:=r1*(1/(1+z/n))*exp(z/n);
    if n=d1 then
    begin
    write(#13,d1/l*100:0:1,'%');
    d1:=d1+d;
    end;
    end;
    r2:=exp(C*z)/z*r1;
    writeln(#13,r2);
    until false;
    end.
    ————————————————-
  24. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Первая ничуть не лучше. После 15 минут счёта дала 9 знаков. За приемливое время можно получить 5-6. Как за это время калькулятор Windows даёт 32 знака если не использует формулу с длинным рядом чисел Стирлинга?
    ——————————-
    {$N+}

    const
    d=100000; { Уменьшить для большей частоты вывода на экран состояния }
    l=1000000; { Увеличить для большей точности вычисления }

    var
    z,r1,r2:extended;
    n,d1:longint;

    begin
    repeat
    readln(z);
    z:=z+1;
    r1:=exp(ln(1+1/1)*z)/(1+z/1);
    d1:=d;
    for n:=2 to l do
    begin
    r1:=r1*exp(ln(1+1/n)*z)/(1+z/n);
    if n=d1 then
    begin
    write(#13,d1/l*100:0:1,'%');
    d1:=d1+d;
    end;
    end;
    r2:=1/z*r1;
    writeln(#13,r2);
    until false;
    end.
    ————————
  25. Vladimirovich Консультант

    • Ветеран
    • Заблокирован
    • Старожил
    Рег.:
    27.09.2006
    Сообщения:
    6.007
    Симпатии:
    810
    Репутация:
    31
    Нарушения:
    31
    Адрес:
    https://quantoforum.ru/
    Оффлайн
    Pia, надеюсь, Вы не собираетесь побеседовать еще и о тонкостях программирования?
    Если Вы в цикле до миллиона сначала берете логарифм а потом опять возводите в степень е, то суперскорости ожидать не стоит :)
    И учтите, что формулы для точного определения чего либо и быстро сходящиеся асимптотические ряды для приближенных вычислений обычно разные вещи.
    ( И я не давал рекомендаций использовать формулы выше для вычислений. )
  26. Крыс Учаcтник

    • Участник
    Рег.:
    22.11.2006
    Сообщения:
    1.848
    Симпатии:
    1
    Репутация:
    0
    Оффлайн
    М-да...
    Наметилась утечка мозгов с ветки "Университет" на "Кухню". :)
  27. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Цикл был не миллион, а 2 миллиарда. А что, быстрее находить логарифм второй части, чем возводить в степень первую?
  28. Kir Старожил

    • Участник
    • Старожил
    Рег.:
    08.02.2007
    Сообщения:
    1.207
    Симпатии:
    223
    Репутация:
    22
    Оффлайн
    :)
  29. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Ага. На пальцах считать.
    Вообще, хватит кривляться. Ответ на первый мой вопрос: нет, нельзя.
  30. krey Михаил Кройтор

    • Команда форума
    Рег.:
    10.04.2006
    Сообщения:
    3.709
    Симпатии:
    50
    Репутация:
    1
    Адрес:
    Кишинев
    Оффлайн
    туплю
    =exp(ln(2)*z/(1+z))
    и вообще, програмка требует оптимизаций. всем читать Карниган, Пайк "Практика Программирования"!!!
  31. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    нет, exp(ln(1+1/1)*z)/(1+z/1) = exp(ln(2)*z-ln(1+z)) = exp(ln(2)*z)/(1+z)
    1/1 и z/1 я написал для наглядности, что n=1.
  32. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Обновил программу в первом посте :p
  33. Mustitz Заслуженный

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    30.09.2006
    Сообщения:
    3.546
    Симпатии:
    1.265
    Репутация:
    36
    Адрес:
    Киев
    Оффлайн
    Чего-то не понял. Не мудрствуя лукаво, за 30 мин пишется нечто вроде этого:

    Код:
    program Factorial;
    {$APPTYPE CONSOLE}
    uses
      SysUtils;
    
    function Sum(const A, B: string): string;
    var
      LenA, LenB: Integer;
      IdxA, IdxB: Integer;
      Next, DigitSum: Integer;
      I: Integer;
    begin
      LenA := Length(A);
      LenB := Length(B);
    
      if LenA < LenB then
      begin
        Result := Sum(B, A);
        Exit;
      end;
    
      SetLength(Result, LenA);
      Next := 0;
    
      for I := 0 to LenA-1 do
      begin
        IdxA := LenA - I;
        IdxB := LenB - I;
        DigitSum := Byte(A[IdxA]) - Byte('0') + Next;
        if IdxB >= 1 then
          DigitSum := DigitSum + Byte(B[IdxB]) - Byte('0');
    
        Byte(Result[IdxA]) := (DigitSum mod 10) + Byte('0');
        Next := DigitSum div 10;
      end;
    
      if Next <> 0 then
        Result := Char(Next + Byte('0')) + Result;
    end;
    
    function Prod(const A: string; B: Char; Shift: Integer): string; overload;
    var
      LenA: Integer;
      DigitA, DigitB, DigitProd: Integer;
      Next: Integer;
      I: Integer;
    begin
      LenA := Length(A);
      DigitB := Byte(B) - Byte('0');
    
      SetLength(Result, LenA + Shift);
    
      for I := 0 to Shift-1 do
        Result[LenA + Shift - I] := '0';
    
      Next := 0;
    
      for I := LenA downto 1 do
      begin
        DigitA := Byte(A[i]) - Byte('0');
        DigitProd := DigitA * DigitB + Next;
        Byte(Result[i]) := (DigitProd mod 10) + Byte('0');
        Next := DigitProd div 10;
      end;
    
      if Next <> 0 then
        Result := Char(Next + Byte('0')) + Result;
    end;
    
    function Prod(const A, B: string): string; overload;
    var
      LenA, LenB: Integer;
      I, Shift: Integer;
    begin
      LenA := Length(A);
      LenB := Length(B);
    
      if LenA < LenB then
      begin
        Result := Sum(B, A);
        Exit;
      end;
    
      if LenB < 1 then
      begin
        Result := '';
        Exit;
      end;
    
      Result := Prod(A, B[LenB], 0);
      Shift := 1;
    
      for I := LenB-1 downto 1 do
      begin
        Result := Sum(Result, Prod(A, B[i], Shift));
        Shift := Shift + 1;
      end;
    end;
    
    function Fact(Value: Integer): string;
    var
      I: Integer;
    begin
      Result := '1';
      for I := 2 to Value do
        Result := Prod(Result, IntToStr(I));
    end;
    
    var
      A: Integer;
    
    begin
      repeat
        Write('A = '); ReadLn(A);
        if A < 0 then Break;
        WriteLn(Fact(A));
        WriteLn;
        if A = 0 then Break;
      until False;
    end.
  34. TopicStarter Overlay

    Pia Учаcтник

    • Участник
    Рег.:
    11.06.2007
    Сообщения:
    537
    Симпатии:
    0
    Репутация:
    0
    Оффлайн
    Ну-ну. Поробуйте этой программой найти (16!)! или 16.5! или -0.5!
  35. Mustitz Заслуженный

    • Заслуженный
    • Участник
    • Старожил
    Рег.:
    30.09.2006
    Сообщения:
    3.546
    Симпатии:
    1.265
    Репутация:
    36
    Адрес:
    Киев
    Оффлайн
    Факториал это функция, определенная только на множестве целых положительных чисел. Существует 2^2^алеф-нуль функций, которые принимают в целых положительных точках значения, равные факториалу. Вам какую?

    Чтобы найти 16!! нужен просто комп пошустрее. Но как ты по другому получишь точное значение факториала? :)

    А так задача сформулирована некорректно: надо задать точность, количество операций. А так изучай второй том Кнута, выбирай более точное представление действительных чисел, бери да реализуй формулу Стирлинга, ...

Поделиться этой страницей