Gamma-Funktion Golf


17

Gegeben eine reelle Zahl tin (-10^9,13)(ohne -10^9oder 13) als Eingabe, Ausgabe Γ(t), auch bekannt als die Gamma-Funktion , die wie folgt definiert ist:

Definition der Gammafunktion

Sie können weder eine integrierte Gamma-Funktion verwenden, um diese Aufgabe zu lösen, noch integrierte numerische oder symbolische Integrationsfunktionen. Ihre Ausgabe sollte auf 6 signifikante Stellen genau sein oder innerhalb 10^-6des tatsächlichen Werts liegen, je nachdem, welcher Wert für den angegebenen Wert weniger einschränkend ist. Die in Python integrierte Gamma-Funktion wird zur Ermittlung des tatsächlichen Werts verwendet. Sie können davon ausgehen Γ(t), dass definiert ist - das heißt, dass es tsich entweder um eine positive reelle Zahl oder eine nicht ganzzahlige negative reelle Zahl handelt - und dass |Γ(t)| ≤ 10^9. Hier ist ein Referenzprogramm, mit dem Sie mithilfe der in Python integrierten Gamma-Funktion die tatsächlichen Werte ermitteln können.

Beispiele

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

Regeln

  • Das ist , also gewinnt die kürzeste Antwort (in Bytes).
  • Standardlücken sind verboten.
  • Die Ein- und Ausgabe kann auf die für Ihre Sprache als Standard geltende Weise erfolgen.
  • Sie können ein vollständiges Programm, eine Funktion oder alles schreiben, was normalerweise als gültige Antwort für Ihre Sprache angesehen wird

Bestenliste

Das Stapel-Snippet am Ende dieses Beitrags generiert die Rangliste aus den Antworten a) als Liste der kürzesten Lösungen pro Sprache und b) als Gesamtrangliste.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

## Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihren Score zu verbessern, Sie können alte Rechnungen in der Überschrift halten, indem man sich durch das Anschlagen. Zum Beispiel:

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

Wenn Sie mehrere Zahlen in Ihre Kopfzeile aufnehmen möchten (z. B. weil Ihre Punktzahl die Summe von zwei Dateien ist oder wenn Sie die Strafen für Interpreter-Flags separat auflisten möchten), stellen Sie sicher, dass die tatsächliche Punktzahl die letzte Zahl in der Kopfzeile ist:

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

Sie können den Namen der Sprache auch als Link festlegen, der dann im Snippet angezeigt wird:

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


1
Bitte geben Sie explizite Grenzen für t an, sodass | gamma (t) | <10 ^ 9
flawr

Der Link ist keine Referenzimplementierung, ...
Sergiol

@sergiol Umformuliert
Mego

Antworten:


2

Pyth, 21 Bytes

Wie bei meiner TI-BASIC-Antwort konnte ich dies nicht mit den vollständigen 8 ^ 10-Iterationen testen, aber bei kleineren Fällen scheint alles in Ordnung zu sein.

cu*Gc^hc1HQhcQHS^8T1Q

Erläuterung:

                            [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

Versuchen Sie es hier mit 2000 Iterationen anstelle von 8 ^ 10.


10

C ++ 14, 86 85 81 Bytes

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

Ich habe nicht viel Zeit damit verbracht. Ich habe nur die Annäherung betrachtet, die (in der Art von Bytes) am einfachsten zu implementieren schien. Die Berechnung des Werts wird einige Zeit in Anspruch nehmen (da sich die Schleife über alle positiven Ganzzahlen erstreckt), die Zeitbeschränkung ist jedoch in der Abfrage nicht angegeben. Es ist eine anonyme Funktion (Lambda), die ein beliebiges Argument (konvertierbar in Twelches pow(double, T)und aufrufbar) annimmt operator/(T,int)und zurückgibt double.

Ungolfed mit Gebrauch

#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 Natürlich ist es das! Vielen Dank.
Zereges,

Welchen Wert haben Sie für -10 ^ 9 und für 10 ^ 9? Ich möchte zuerst wissen, wie gut deine Sachen funktionieren, bevor du meine Zustimmung bekommst.
Fehler

@ Mego Microsoft Compiler benötigt keines dieser Includes.
Zereges

@ MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Zereges

@flawr Das Minenprogramm gibt 0 für aus, gamma(-10e9)aber OP gibt an, dass nur Parameter berücksichtigt werden können, für die eine Gammafunktion definiert ist. gamma(10e9)kehrt zurück inf, während die eingebaute Gamma-Funktion von Python zur Bestimmung des tatsächlichen Werts verwendet wird, heißt esOverflowError: math range error
Zereges

7

Minkolang 0.12 , 35 34 25 Bytes

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

Dies stoppt zwar mit einem Fehler (beim Versuch, durch 0 zu teilen), dies ist jedoch gemäß Metakonsens zulässig . Fügen Sie .am Ende ein für ein Programm hinzu, das normalerweise angehalten wird. Probieren Sie alle Testfälle gleichzeitig aus. (Die Schleife durchläuft nur 1e4-mal, sodass sie eher früher als später beendet wird.)

Erläuterung

Zereges verwendete eine der alternativen, unendlichen Produktdefinitionen . Wie sich herausstellt, ist das andere System in Minkolang viel leichter umzusetzen.

Eulers alternative Formulierung der Gammafunktion

Dies ist eine Grenze, nbis ins Unendliche geht, was bedeutet , dass ich beide berechnen kann n!und (t+n)wie ich gehe. Also nehme ich heraus 1/t(weil 0!=1) und n^tweil dieser nicht sequentiell berechnet werden kann, ohne den Endwert von zu kennen n. Wie es passiert, weil ndas Limit ist, kann ich es zweimal verwenden. Einmal als Faktor in der Berechnung und einmal als Anzahl der Durchläufe der Schleife.

Ein sequentielles unendliches Produkt muss mit etwas beginnen, normalerweise 1. In diesem Fall ist es n^t/t. Im Rumpf der Schleife berechne k/(t+k)und multipliziere ich dies mit dem bisherigen Produkt. Am Ende wurde das gesamte Produkt berechnet und ausgegeben. Dies ist im Wesentlichen das, was mein Programm tut, und zwar so nhoch, dass die Antwort präzise genug ist.

Explosionsversion des unendlichen Produkts

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

Da es keine gibt ., wickelt es sich um und beginnt von vorne. Allerdings nproduziert jetzt , -1da die Eingabe leer ist, die schließlich führt zu durch 0 zu teilen versuchen, die das Programm stoppt.


5

Julia, 141 Bytes

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

Dadurch wird eine unbenannte Lambda-Funktion erstellt, die eine reelle Zahl akzeptiert und eine reelle Zahl zurückgibt. Es verwendet die Näherung von Spounge , um Gamma zu berechnen.

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

Sehr, sehr spätes Golfen, 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)))sollte aber für 137 Bytes funktionieren (zumindest in Julia 0.6)
Mr. Xcoder

3

Japt, 45 Bytes

Japt ist eine verkürzte Version von Ja vaScri pt . Dolmetscher

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

Natürlich dauert 1e9 = 1,000,000,000 Iterationen ewig, also versuchen Sie zum Testen, das 9durch a zu ersetzen6 . (1e6 ist auf ~ 5 signifikante Zahlen genau. Die Verwendung von 1e8 bei einer Eingabe von 12genügt, um die ersten sechs zu erhalten.)

Testergebnisse: (mit 1e7-Präzision)

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

Wie es funktioniert

         // 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 Bytes

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

Dies verwendet den gleichen Algorithmus wie Zereges.

Vorsichtsmaßnahme: Ich habe dies noch nicht mit den vollständigen 1e9-Iterationen getestet. Aufgrund der Zeit, die für kleinere Werte benötigt wird, erwarte ich eine Laufzeit in der Größenordnung von Monaten . Es scheint jedoch zu konvergieren, und es sollte keine Probleme mit Rundungsfehlern geben. TI speichert Zahlen als dezimale Gleitkommazahlen mit einer Genauigkeit von 14 Stellen.


Du hast es nicht getestet ?!
TanMath,

1
@ TanMath würde ich, aber ich brauche meinen Rechner für eine Abschlussprüfung im nächsten Monat.
Lirtosiast

3

Python 3, 74 68 78 73 Bytes

Vielen Dank an @Mego und @xnor

Dies ist eine Übersetzung der C ++ - Antwort von Zereges. Grundsätzlich ist dies eine alternative Definition der Gammafunktion, daher genauer (und was großartig ist, dass weniger Bytes verwendet werden!)

Es tut mir leid für alle Fehler!

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

1
Die +1Reichweite spielt keine Rolle, wenn Sie mit Milliarden zu tun haben. Außerdem sollten Sie angeben, dass dies Python 3 ist - Sie benötigen from __future__ import divisioneine Float-Division und ein paar Terabyte RAM, um mit der Tatsache fertig zu werden, dass rangein Python 2 eine Liste zurückgegeben wird. Außerdem können Sie 1.0s durch 1s ersetzen und off 4 rasieren Bytes.
Mego

2
@ TanMath: ^ist xor, meintest du nicht was die **Potenzierung anbelangt ?
Jermenkoo

3
int(1e9)ist nur 10**9, und Sie brauchen nicht die Eltern herum (1+1/i)**z.
15.

3

Python, 348 448 407 390 389 Bytes

Besonderer Dank geht an @Mego!

Ein durchgestrichener 448 ist (fast) immer noch ein 448! : p

Dies basiert auf der Lanzcos-Näherung. Von hier aus Golf gespielt

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
Bitte spielen Sie Ihre Eingabe durch, indem Sie mindestens Leerzeichen (die Leerzeichen vor und nach - = und in import *zum Beispiel) entfernen und einen einstelligen Funktionsnamen verwenden. Beachten Sie auch, dass Sie nur echte Eingaben unterstützen müssen.
Lirtosiast

@ThomasKwa Ich habe es bearbeitet. Meine ursprüngliche Version hat nicht funktioniert, hier ist eine neuere.
TanMath,

@Mego bearbeitet ...
TanMath

Dies führt zu einem Rekursionsfehler. Entfernen Sie das Symbol z-=1;in der ersten Zeile von gamma, um den Fehler zu beheben. Sie sollten auch umbenennen gamma, gum Bytes zu speichern und Namenskonflikte zu vermeiden cmath.gamma. Löschen Sie auch die äußeren führenden Nullen.
Mego

1

Julia, 41 Bytes

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

Dies ist eine Übersetzung der C ++ - Antwort von Zereges. Während meine andere Julia-Antwort sofort endet, ist dies ziemlich langsam. Es berechnet die Testfälle in jeweils wenigen Sekunden auf meinem Computer.

Ungolfed:

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

1

Prolog, 114 Bytes

Dies ist eine Übersetzung der C ++ - Antwort von Zereges.

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

Probieren Sie es hier online aus.
Führen Sie es mit einer Abfrage des Formulars aus:

p(12).

Das Ausführen mit 1e9-Rekursionen dauert ungefähr 15 Minuten.
Wenn Sie es auf 1e6 verringern, dauert es ungefähr 1 Sekunde, was das Testen erleichtert (aber weniger genau macht).
Das Ausführen in einem Interpreter auf Ihrem Computer / Laptop ist wahrscheinlich auch für die meisten Menschen schneller.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.