Oceń funkcję Zeta Riemanna przy liczbie zespolonej

11

Wprowadzenie

Znalazłem to pytanie, które zostało zamknięte, ponieważ było niejasne, ale był to fajny pomysł. Zrobię co w mojej mocy, aby było to wyraźne wyzwanie.

Funkcja Riemanna Zeta jest funkcją specjalną, która jest zdefiniowana jako kontynuacja analityczna

wprowadź opis zdjęcia tutaj

do złożonej płaszczyzny. Istnieje wiele równoważnych formuł, które sprawiają, że jest to interesujące dla golfa kodowego.

Wyzwanie

Napisz program, który pobiera 2 zmiennoprzecinkowe dane wejściowe (rzeczywistą i urojoną część liczby zespolonej) i ocenia funkcję Riemanna Zety w tym punkcie.

Zasady

  • Wejście i wyjście za pośrednictwem wejścia LUB wartości funkcji konsoli lub powrotu
  • Wbudowane liczby zespolone są niedozwolone, użyj liczb zmiennoprzecinkowych (liczba, liczba podwójna, ...)
  • Żadnych funkcji matematycznych oprócz funkcji + - * / pow logwyzwalających o wartościach rzeczywistych (jeśli chcesz zintegrować, użyj funkcji gamma, ... musisz zawrzeć tę definicję funkcji w kodzie)
  • Wejście: 2 pływaki
  • Wyjście: 2 pływaki
  • Twój kod musi zawierać wartość, która daje teoretycznie dowolną precyzję, gdy zostanie wykonana dowolnie duża / mała
  • Zachowanie na wejściu 1 nie jest ważne (jest to jedyny biegun tej funkcji)

Najkrótszy kod w bajtach wygrywa!

Przykład wejścia i wyjścia

Wejście:

2, 0

Wynik:

1.6449340668482266, 0

Wejście:

1, 1

Wynik:

0,5821580597520037, -0,9268485643308071

Wejście:

-1, 0

Wynik:

-0,08333333333333559, 0

Jens Renders
źródło
1
Jaka jest wymagana dokładność wyjściowa? Nie jestem pewien, czy rozumiem, że Twój kod musi zawierać wartość, która daje teoretycznie dowolną precyzję, gdy zostanie ustawiona dowolnie duża / mała . Czy masz na myśli maksymalną wartość pętli niż gdy zwiększenie bez ograniczenia daje większą precyzję? Czy tę wartość można zakodować na stałe?
Luis Mendo,
@DonMuesli Oznacza to, że precyzja zależy od parametru, powiedzmy N, który możesz nadać dowolnej wartości, ale dla dowolnej precyzji możesz ustawić N na tyle, aby osiągnąć tę precyzję. Słowo teoretycznie istnieje, ponieważ nie należy się martwić ograniczoną precyzją maszyny lub języka.
Jens Renders
W celu dalszego wyjaśnienia N: czy wystarczy, że dla dowolnego powiązania epsi danych wejściowych xistnieje coś, Nco oblicza się zeta(x)do wewnątrz eps; lub musi istnieć coś, Nco zależy tylko epsi gwarantuje, że dla dowolnej x(lub być może dla dowolnej xwięcej niż danej funkcji epsbieguna) osiągnie granicę; lub może Nzależeć x, ale odpowiedzi powinny wyjaśniać, jak obliczyć Npodane xi eps? (Moja teoria liczb analitycznych nie jest zbyt duża, ale podejrzewam, że opcje 2 i 3 będą poza wszystkim oprócz jednego lub dwóch zwykłych plakatów).
Peter Taylor
@PeterTaylor N wystarczająco duży: Dla każdego xi dla każdego epsmusi istnieć Ptaki, że dla wszystkich N>Pdanych wyjściowych jest bliżej niż epsdo dokładnej wartości. Czy to jasne? Czy muszę to wyjaśnić w przypadku wystarczająco małych liter N?
Jens Renders
Nie, to dość jasne.
Peter Taylor,

Odpowiedzi:

8

Python - 385

Jest to prosta implementacja równania 21 z http://mathworld.wolfram.com/RiemannZetaFunction.html Wykorzystuje konwencję Pythona do opcjonalnych argumentów; jeśli chcesz określić precyzję, możesz przekazać trzeci argument do funkcji, w przeciwnym razie domyślnie używa 1e-24.

import numpy as N
def z(r,i,E=1e-24):
 R=0;I=0;n=0;
 while(True):
  a=0;b=0;m=2**(-n-1)
  for k in range(0,n+1):
   M=(-1)**k*N.product([x/(x-(n-k))for x in range(n-k+1,n+1)]);A=(k+1)**-r;t=-i*N.log(k+1);a+=M*A*N.cos(t);b+=M*A*N.sin(t)
  a*=m;b*=m;R+=a;I+=b;n+=1
  if a*a+b*b<E:break
 A=2**(1-r);t=-i*N.log(2);a=1-A*N.cos(t);b=-A*N.sin(t);d=a*a+b*b;a=a/d;b=-b/d
 print(R*a-I*b,R*b+I*a)
RT
źródło
z(2,0)daje niepoprawną wartość, powinna być pi ^ 2/6.
GuillaumeDufay
4

Python 3 , 303 297 bajtów

Ta odpowiedź jest oparta na odpowiedzi RT na Python z kilkoma modyfikacjami:

  • Po pierwsze, Binomial(n, k)jest definiowany jako, p = p * (n-k) / (k+1)który zmienia Binomial(n,k)się Binomial(n,k+1)przy każdym przejściu pętli for.
  • Po drugie, (-1)**k * Binomial(n,k)stał się, p = p * (k-n) / (k+1)co zmienia znak na każdym kroku pętli for.
  • Po trzecie, zmieniono whilepętlę, aby natychmiast sprawdzić, czy a*a + b*b < E.
  • Po czwarte, operator bitowe nie ~jest używany w kilku miejscach, gdzie będą pomagać w golfa, używając tożsamości, takie jak -n-1 == ~n, n+1 == -~ni n-1 == ~-n.

Wprowadzono kilka innych małych modyfikacji dla lepszego gry w golfa, takich jak umieszczenie forpętli na jednej linii i wywołanie printna jednej linii z kodem przed nią.

Sugestie dotyczące gry w golfa mile widziane. Wypróbuj online!

Edycja: -6 bajtów z szeregu małych zmian.

import math as N
def z(r,i,E=1e-40):
 R=I=n=0;a=b=1
 while a*a+b*b>E:
  a=b=0;p=1;m=2**~n
  for k in range(1,n+2):M=p/k**r;p*=(k-1-n)/k;t=-i*N.log(k);a+=M*N.cos(t);b+=M*N.sin(t)
  a*=m;b*=m;R+=a;I+=b;n+=1
 A=2**-~-r;t=-i*N.log(2);x=1-A*N.cos(t);y=A*N.sin(t);d=x*x+y*y;return(R*x-I*y)/d,(R*y+I*x)/d
Sherlock9
źródło
1

Axiom, 413 315 292 bajtów

p(n,a,b)==(x:=log(n^b);y:=n^a;[y*cos(x),y*sin(x)]);z(a,b)==(r:=[0.,0.];e:=10^-digits();t:=p(2,1-a,-b);y:=(1-t.1)^2+t.2^2;y=0=>[];m:=(1-t.1)/y;q:=t.2/y;n:=0;repeat(w:=2^(-n-1);abs(w)<e=>break;r:=r+w*reduce(+,[(-1)^k*binomial(n,k)*p(k+1,-a,-b) for k in 0..n]);n:=n+1);[r.1*m-q*r.2,m*r.2+r.1*q])

Zaimplementowałoby to również równanie 21 z http://mathworld.wolfram.com/RiemannZetaFunction.html Powyżej powinna być tutaj jedna z interpretowanych funkcji Axiom z (a, b) tutaj 16x wolniej niż ta poniżej funkcji Zeta (a, b) [ to powinna być ta skompilowana] wszyscy nieposortowani i skomentowali [1 sekunda dla Zeta () wobec 16 sekund dla z () dla jednej wartości 20 cyfr po punkcie zmiennoprzecinkowym]. W przypadku pytania o cyfrę należałoby wybrać dokładność, wywołując cyfry (); funkcja, na przykład cyfry (10); z (1,1) powinien wypisać 10 cyfr po punkcie, ale cyfry (50); z (1,1) powinien wypisać 50 cyfr po punkcie.

-- elevImm(n,a,b)=n^(a+i*b)=r+i*v=[r,v]
elevImm(n:INT,a:Float,b:Float):Vector Float==(x:=log(n^b);y:=n^a;[y*cos(x),y*sin(x)]::Vector Float);

--                      +oo               n
--                      ---              ---
--             1        \       1        \            n 
--zeta(s)= ---------- * /     ------  *  /    (-1)^k(   )(k+1)^(-s)
--          1-2^(1-s)   ---n  2^(n+1)    ---k         k  
--                       0                0


Zeta(a:Float,b:Float):List Float==
  r:Vector Float:=[0.,0.]; e:=10^-digits()

  -- 1/(1-2^(1-s))=1/(1-x-i*y)=(1-x+iy)/((1-x)^2+y^2)=(1-x)/((1-x)^2+y^2)+i*y/((1-x)^2+y^2)    

  t:=elevImm(2,1-a,-b);
  y:=(1-t.1)^2+t.2^2;
  y=0=>[] 
  m:=(1-t.1)/y; 
  q:=t.2/y
  n:=0
  repeat
     w:=2^(-n-1)
     abs(w)<e=>break  --- this always terminate because n increase
     r:=r+w*reduce(+,[(-1)^k*binomial(n,k)*elevImm(k+1,-a,-b) for k in 0..n])
     n:=n+1
  -- (m+iq)(r1+ir2)=(m*r1-q*r2)+i(m*r2+q*r1)
  [r.1*m-q*r.2,m*r.2+r.1*q]

this is one test for the z(a,b) function above:

(10) -> z(2,0)
   (10)  [1.6449340668 482264365,0.0]
                                              Type: List Expression Float
(11) -> z(1,1)
   (11)  [0.5821580597 520036482,- 0.9268485643 3080707654]
                                              Type: List Expression Float
(12) -> z(-1,0)
   (12)  [- 0.0833333333 3333333333 3,0.0]
                                              Type: List Expression Float
(13) -> z(1,0)
   (13)  []
RosLuP
źródło