Гамма-функция Гольф

17

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

определение гамма-функции

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

Примеры

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

правила

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

Leaderboard

Фрагмент стека в нижней части этого поста создает таблицу лидеров из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

## 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

Mego
источник
1
Пожалуйста, предоставьте явные оценки для t, чтобы | gamma (t) | <10 ^ 9
flawr
Ссылка не является ссылочной реализацией, ...
sergiol
@sergiol переписал его
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.

lirtosiast
источник
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
}
Zereges
источник
@Mego Конечно, это так! Благодарю.
Zereges
Так какое значение вы получите за -10 ^ 9 и за 10 ^ 9? Прежде всего, я хочу узнать, насколько хорошо работает ваш материал, прежде чем вы получите мое мнение.
flawr
@Mego Microsoft компилятор не нуждается ни в одном из этих включений.
Zereges
@MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Zereges
@flawr Моя программа выводит 0 для, gamma(-10e9)но OP указал, что могут рассматриваться только параметры, для которых определена гамма-функция. gamma(10e9)возвращается inf, в то время как Python встроенного Gamma функция будет использоваться для определения фактического значения говоритOverflowError: math range error
Zereges
7

Минколанг 0,12 , 35 34 25 байт

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

Это останавливается с ошибкой (при попытке деления на 0), но это разрешено согласно мета-консенсусу . Добавьте .в конце программу, которая обычно останавливается. Попробуйте все тестовые случаи одновременно. (Цикл повторяется только 1e4 раза, поэтому он закончится раньше, чем позже.)

объяснение

Zereges использовал одно из альтернативных, бесконечных определений продукта . Как выяснилось, другой гораздо удобнее реализовать в Минколанге.

Альтернативная формулировка Эйлера гамма-функции

Это предел в nбесконечности, что означает, что я могу рассчитывать и то, n!и другое (t+n). Таким образом, я вынимаю 1/t(потому что 0!=1) и n^tпотому, что это не может быть вычислено последовательно, не зная конечного значения n. Как это бывает, потому что nэто предел, я могу использовать его дважды. Один раз как фактор в расчете и один раз как количество раз, чтобы запустить цикл.

Последовательный бесконечный продукт должен начинаться с чего-то, обычно 1. В данном случае это так n^t/t. В теле цикла я вычисляю k/(t+k)и умножаю это на произведение. В конце концов, весь продукт был рассчитан и выведен. По сути, это то, что делает моя программа, nдостаточно высокая, чтобы ответ был достаточно точным.

взорванная версия бесконечного произведения

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])))

Это создает безымянную лямбда-функцию, которая принимает действительное число и возвращает действительное число. Оно использует приближение Spounge для вычисления гаммы.

Ungolfed:

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).
ETHproductions
источник
3

TI-BASIC, 35 байтов

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

Это использует тот же алгоритм, что и Zereges.

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

lirtosiast
источник
Вы не проверяли это ?!
TanMath
1
@TanMath Я бы хотел, но мне нужен калькулятор для финального экзамена в следующем месяце.
lirtosiast
3

Python 3, 74 68 78 73 байта

Спасибо @Mego и @xnor

Это перевод ответа С ++ Зерегеса. По сути, это альтернативное определение гамма-функции, следовательно, более точное (и то, что замечательно, это то, что использует меньше байтов!)

Прошу прощения за все ошибки!

def g(z,v=1):
 for i in range(1,10**9):v*=(1+1/i)**z/(1+z/i)
 return v/z
TanMath
источник
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

Python, 348 448 407 390 389 байт

Отдельное спасибо @Mego!

Вычеркнутый 448 - это (почти) по-прежнему 448! :п

Это основано на приближении Ланцкоса. Гольф от сюда

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
TanMath
источник
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

Это перевод ответа Серега на С ++. В то время как мой другой ответ Джулии заканчивается мгновенно, это довольно медленно. Он вычисляет тестовые случаи за пару секунд каждый на моем компьютере.

Ungolfed:

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).

Запуск его с 1e9 рекурсиями занимает около 15 минут.
Если вы уменьшите его до 1e6, это займет около 1 секунды, что упрощает (но менее точно) тестирование.
Запуск его в интерпретаторе на вашем компьютере / ноутбуке, скорее всего, быстрее для большинства людей.

Emigna
источник
0

Mathematica, 40 байт

NProduct[(1+1/n)^#/(1+#/n),{n,1,∞}]/#&
alephalpha
источник