Gamma Function Golf


17

Дано реальне число tв (-10^9,13)(не включаючи -10^9або 13) як вхід, вихід Γ(t), також відомий як Гамма-функція , яка визначається наступним чином:

визначення гамма-функції

Ви не можете використовувати вбудовану функцію Gamma для вирішення цього завдання, а також не можете використовувати вбудовані числові чи символьні функції інтеграції. Вихід повинен бути точним до 6 значущих цифр або в межах 10^-6фактичного значення, залежно від того, що є менш обмежуючим для даного значення. Вбудована функція Gamma Python буде використовуватися для визначення фактичного значення. Ви можете припустити Γ(t), що визначено - тобто це tчи додатне дійсне число, чи не ціле негативне дійсне число - і це |Γ(t)| ≤ 10^9. Ось довідкова програма, яку ви можете використовувати для отримання фактичних значень, використовуючи вбудовану функцію Gamma Python.

Приклади

1 -> 1.000000
-2.5 -> -0.945309
3.14159265 -> 2.288038
-2.71828182846 -> -0.952682
12 -> 39916800.000000
0.5 -> 1.772454
8.675309 -> 20248.386956
-10.1 -> -0.000002

Правила

  • Це , тому найкоротша відповідь (у байтах) виграє.
  • Стандартні лазівки заборонені.
  • Введення та виведення даних можуть здійснюватися будь-яким способом, який вважається стандартним для вашої мови.
  • Ви можете написати повну програму, функцію чи будь-що, що зазвичай вважається правильною відповіддю для вашої мови

Таблиця лідерів

Фрагмент стека внизу цієї публікації генерує таблицю лідерів з відповідей а) як список найкоротших варіантів для кожної мови та б) як загальну таблицю лідерів.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

## Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Якщо ви хочете включити у свій заголовок декілька чисел (наприклад, тому що ваш результат - це сума двох файлів або ви хочете окремо перерахувати штрафні санкції для перекладача), переконайтесь, що фактичний результат - це останнє число у заголовку:

## Perl, 43 + 2 (-p flag) = 45 bytes

Ви також можете зробити ім'я мови посиланням, яке з’явиться у фрагменті:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


1
Будь ласка, надайте чіткі межі для t таких, що | gamma (t) | <10 ^ 9
недолік

Посилання не є еталонною реалізацією, ...
sergiol

@sergiol Reworded it
Mego

Відповіді:


2

Pyth, 21 байт

Як і в моїй відповіді TI-BASIC, я не зміг перевірити це за допомогою повних 8 ^ 10 ітерацій, але все здається гарним у менших випадках.

cu*Gc^hc1HQhcQHS^8T1Q

Пояснення:

                            [implicit: Q=input]
                ^8T         8**10
               S^8T         [1,2,3,...,8**10]
  *Gc^hc1HQhcQH             lambda G,H:G*(1+1/H)**Q/(1+Q/H)
                   1        Base case
 u*Gc^hc1HQhcQHS^8T1        Reduce with base case 1
c                   Q       Divide by Q

Спробуйте тут з 2000 ітерацій замість 8 ^ 10.


10

C ++ 14, 86 85 81 байт

[](auto t){auto v=1.;for(int x=1;x<1e9;++x)v*=pow(1+1./x,t)/(1+t/x);return v/t;};

Я не витрачав багато часу на цей. Я просто подивився на наближення, яке здавалося найпростішим для реалізації (у манері байтів). Для обчислення значення знадобиться деякий час (оскільки цикл перевищує всі додатні цілі числа), але обмеження в часі не вказано в виклику. Це анонімна функція (лямбда), яка приймає будь-який аргумент (конвертований в T який pow(double, T)і operator/(T,int)можна викликати) і повертає double.

Безголовка з використанням

#include <iostream>
int main()
{
    auto r = [](auto t)
    {
        auto v = 1.;
        for (int x = 1; x < 1e9; ++x)
            v *= pow(1 + 1. / x, t) / (1 + t / x);
        return v / t;
    };
    std::cout << r(-2.71828182846); // outputs -0.952682
}

@Mego Звичайно, так! Спасибі.
Зереги

Отже, яке значення o ви отримуєте за -10 ^ 9 і за 10 ^ 9? Я спершу хочу знати, наскільки добре працюють ваші речі, перш ніж ви отримаєте мою нагороду.
flawr

@Mego Компілятор Microsoft не потребує жодного з цих програм.
Зереги

@MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Зерегеш

Програма @flawr Mine виводить 0 для, gamma(-10e9)але OP заявила, що можна вважати лише параметри, для яких визначена гамма-функція. gamma(10e9)повертається inf, в той час як Python вбудованого Gamma функція буде використовуватися для визначення фактичного значення говоритьOverflowError: math range error
Zereges

7

Minkolang 0,12 , 35 34 25 байт

n$zl8;dz;z$:r[i1+dz+$:*]N

Це припиняється з помилкою (при спробі розділити на 0), але це дозволено відповідно до мета-консенсусу . .В кінці додайте програму, яка нормально зупиняється. Спробуйте всі тестові справи одразу. (Цикл повторюється лише 1e4 рази, тому він закінчиться швидше, ніж пізніше.)

Пояснення

Зереги використовували одне з альтернативних, нескінченних визначень продукту . Як виявляється, інше набагато приємніше реалізовувати у Мінколангу.

Euler's alternative formulation of the gamma function

Це межа, як і nдо нескінченності, це означає, що я можу обчислити і те, n!і (t+n)як я йду. Тому я виймаю 1/t(тому, що 0!=1) і n^tтому, що не можна обчислювати послідовно, не знаючи кінцевого значення n. Як це буває, оскільки nце межа, я можу використовувати її двічі. Один раз як фактор обчислення і один раз - кількість разів для запуску циклу.

Послідовний нескінченний продукт повинен починатися з чогось, як правило, 1. У цьому випадку це n^t/t. У тілі петлі я обчислюю k/(t+k)та множу це з виробом до цих пір. Зрештою, весь продукт був розрахований і виведений. Це по суті те, що робить моя програма, з nдостатньо високим рівнем відповіді, щоб відповідь була досить точною.

exploded version of the infinite product

n                            Take number from input
 $z                          Store it in the register (this is t; retrieved with z)
   l8;                       10^8 (this is n, the limit)
      d                      n,n
       z;                    n,n^t
         z$:                 n,n^t/t
            r                Reverse stack -> n^t/t,n
             [               For loop that runs n times
              i1+            k
                 d           k,k
                  z+         k,t+k
                    $:       k/(t+k)
                      *      Multiply
                       ]N    Close for loop and output as integer

Як немає ., він загортається і починається спочатку. Однак nтепер виробляється, -1оскільки вхід порожній, що врешті-решт призводить до спроби поділу на 0, що зупиняє програму.


5

Джулія, 141 байт

z->(z-=1;a=90;c(k)=(k=big(k);(-1)^(k-1)/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum([c(k)/(z+k)for k=1:a-1])))

Це створює неназвану лямбда-функцію, яка приймає дійсне число і повертає дійсне число. Він використовує наближення Спаунжа для обчислення Гамми.

Безголовки:

function Γ(z::Real)
    # Spounge's approxmation is for Γ(z+1), so subtract 1
    z -= 1

    # Choose a number for the constant a, which determines the
    # bound on the error
    a = 90

    # Define a function for the sequence c_k
    function c(k::Integer)
        # Convert k to a BigInt
        k = big(k)
        return (-1)^(k-1) / factorial(k-1) * (a-k)^(k-1/2) * exp(a-k)
    end

    # Compute the approximation
    return (z+a)^(z+1/2) * exp(-z-a) * (√(2π) + sum([c(k)/(z+k) for k=1:a-1]))
end

Дуже, дуже пізній гольф, але він z->(z-=1;a=90;c(k)=(k=big(k);(-1)^~-k/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum(c(k)/(z+k)for k=1:a-1)))повинен працювати на 137 байт (принаймні, в Julia 0.6)
Містер Xcoder

3

Japt, 45 байт

Japt - скорочена версія Ja vaScri pt . Перекладач

$for(V=X=1;X<1e9;)$V*=(1+1/X pU /(1+U/X++;V/U

Звичайно, 1e9 = 1 000 000 000 ітерацій триває назавжди, тому для тестування спробуйте замінити на 9a 6. (1e6 точний до ~ 5 значущих цифр. Використання 1e8 на вході 12достатньо, щоб отримати перші шість.)

Результати тестових випадків: (з точністю 1e7)

       1:  1
    -2.5: -0.9453083...
      pi:  2.2880370...
      -e: -0.9526812...
      12:  39916536.5...
     0.5:  1.7724538...
8.675309:  20248.319...
   -10.1: -0.0000022...

Як це працює

         // Implicit: U = input number
$for(    // Ordinary for loop.
V=X=1;   //  Set V and X to 1.
X<1e9;)$ //  Repeat while X is less than 1e9.
V*=      // Multiply V by:
(1+1/X   //  1 plus (1 over X),
pU /     //  to the power of U, divided by
(1+U/X++ //  1 plus (U over X). Increment X by 1.
;V/U     // Output the result of (V over U).

3

TI-BASIC, 35 байт

Input Z
1
For(I,1,ᴇ9
Ans(1+I⁻¹)^Z/(1+Z/I
End
Ans/Z

Для цього використовується той же алгоритм, що і Зерегес.

Caveat: Я насправді цього не перевіряв за допомогою повних ітерацій 1e9; виходячи з часу, необхідного для менших значень, я очікую, що тривалість виконання буде близько місяця . Однак воно, схоже, збігається, і не повинно виникнути проблем із помилками округлення. TI зберігає числа у вигляді десяткових поплавків із 14 цифрами точності.


Ви цього не тестували ?!
TanMath

1
@TanMath Я б хотів, але мені потрібен мій калькулятор для підсумкового іспиту наступного місяця.
lirtosiast

3

Пітон 3, 74 68 78 73 байт

Дякую @Mego та @xnor

Це переклад відповіді C ++ Зерегеса. В основному, це альтернативне визначення гамма-функції, отже, більш точне (і що чудово - це використання менше байтів!)

Мені шкода за всі помилки!

def g(z,v=1):
 for i in range(1,10**9):v*=(1+1/i)**z/(1+z/i)
 return v/z

1
+1На діапазон не має значення , коли ви маєте справу з мільярдами. Крім того, ви повинні вказати, що це Python 3 - вам знадобиться from __future__ import divisionплаваючий поділ і кілька терабайт оперативної пам’яті, щоб боротися з тим, що rangeповертає список в Python 2. Крім того, ви можете замінити 1.0s на 1s і відголити 4 байт
Мего

2
@TanMath: ^це xor, ти не мав на увазі, **як для експоненції?
jermenkoo

3
int(1e9)просто 10**9, і вам не потрібні парони навколо (1+1/i)**z.
xnor

3

Пітона, 348 448 407 390 389 байт

Особлива подяка @Mego!

Перекреслений 448 - це (майже) все ще 448! : с

Це ґрунтується на наближенні Ланкоса. Golfed з тут

from cmath import*
C=[0.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-17‌6.6150291621406,12.507343278686905,-0.13857109526572012,9.984369578019572e-6,1.5‌​056327351493116e-7]
def g(z):
 z-=1;if z.real<0.5:return pi/(sin(pi*z)*gamma(1-z))
 else:
  x=C[0]
  for i in range(1,9):x+=C[i]/(z+i)
  t=z+7.5;return sqrt(2*pi)*t**(z+0.5)*exp(-t)*x

1
Будь ласка, гольф подайте, як мінімум, видаляючи пробіли (пробіли до і після - = і, import *наприклад) та використовуючи ім'я функції з одним символом. Також зауважте, що вам потрібно підтримувати лише реальні дані.
lirtosiast

@ThomasKwa я відредагував це. Моя оригінальна версія не працювала, ось нова.
TanMath

@Mego відредаговано ...
TanMath

Це викликає помилку рекурсії - видаліть z-=1;у першому рядку, gammaщоб виправити її. Ви також повинні перейменовувати gammaна gзбереження байтів і уникати конфліктів з іменами cmath.gamma. Також скиньте сторонні провідні нулі.
Мего

1

Джулія, 41 байт

x->prod([(1+1/i)^x/(1+x/i)for i=1:1E7])/x

Це переклад відповіді Зерегеса С ++. Хоча моя інша відповідь Юлії закінчується миттєво, це досить повільно. Він обчислює тестові випадки за пару секунд на моєму комп’ютері.

Безголовки:

function f(x::Real)
    prod([(1 + 1/i)^x / (1 + x/i) for i = 1:1E7]) / x
end

1

Пролог, 114 байт

Це переклад відповіді Зерегеса С ++.

q(F,F,V,Z):-X is V/Z,write(X).
q(F,T,V,Z):-W is(1+1/F)**Z/(1+Z/F)*V,I is F+1,q(I,T,W,Z).
p(N):-q(1.0,1e9,1,N),!.

Спробуйте це в Інтернеті тут.
Запустіть його із запитом форми:

p(12).

Виконання його за допомогою 1е9 ​​рекурсій займає близько 15 хвилин.
Якщо зменшити його до 1e6, це потребує приблизно 1 секунди, що полегшує (але менш гостро) тестування.
Запуск його в перекладачі на вашому комп'ютері / ноутбуці, швидше за все, швидший і для більшості людей.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.