Berechnen Sie die Ziffern von Pi


15

Dies ist eine etwas andere Aufgabe. Berechnen Sie 1024 hexadezimale Stellen von π, beginnend mit der 1024. hexadezimalen Stelle.

Formal: Ihr Programm sollte in weniger als 1 Minute fertig sein und die folgende Ausgabe erzeugen:

25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e8

Das Programm mit der kürzesten Länge gewinnt. Sie müssen alle Ziffern zur Laufzeit berechnen. Sie müssen den Algorithmus, der π berechnet, nicht implementieren. Wenn Ihre Sprache diese Funktionalität bereits bietet, können Sie sie verwenden.


Hah, sollte einfach sein. (+1, immer noch) Ich wette, ich kann es in weniger als ein paar Sekunden ausführen lassen.
Mateen Ulhaq

@muntoo: Und? Wo ist deine Lösung?
FUZxxl

Ich habe vergessen, es zu tun. :) Übrigens, Geschwindigkeit! = Code-Golf.
Mateen Ulhaq

@muntoo: Ich weiß. Aber ich denke auch, dass 5 Tage eine gute Zeit für eine so einfache Aufgabe sind.
FUZxxl

Antworten:


13

Salbei, 29 char

Dies ist technisch gesehen kein Betrug, da die Ziffern zur Laufzeit berechnet werden. Das heißt, es ist immer noch billig wie die Hölle.

hex(floor(pi*2^8192))[1025:]

1
Auf keinen Fall betrügen.
FUZxxl

11
Mmmm, Boden pi.
Brotkasten

13

Shell-Dienstprogramme: 48

curl -sL ow.ly/5u3hc|grep -Eom 1 '[a-f0-9]{1024}'

  • Alle Ausgaben werden zur Laufzeit "berechnet". (Dank an OP, der die Lösung veröffentlicht)
  • Läuft in weniger als einer Minute. (hängt möglicherweise von der Geschwindigkeit Ihrer Internetverbindung ab)

Normalerweise habe ich solche Lösungen abgelehnt, weil sie ein verbreiteter Missbrauch der Regeln sind und nicht mehr lustig. Aber nur, weil Sie so schlau sind, die mitgelieferte Referenzlösung zu nehmen und zu schreiben. Alle Ausgaben werden zur Laufzeit "berechnet". (danke, dass OP die Lösung gepostet hat ) , ich gebe dir eine positive Bewertung;)
FUZxxl

Golfversion: curl -sL ow.ly/shKGY|grep -Po \\w{99,}(37). Funktioniert in Dash. Bash würde ein zusätzliches Byte benötigen.
Dennis

6

J, 156, 140, 137, 127

d=:3 :'1|+/4 _2 _1 _1*+/(y&(16^-)%1 4 5 6+8*])"0 i.y+9'
,1([:}.'0123456789abcdef'{~[:|.[:<.[:(],~16*1|{.)^:8 d)"0\1024x+8*i.128

Verwendung der BBP-Formel.

Läuft NICHT in weniger als einer Minute (aber wir haben eine J-Antwort: p)

Beispiel für die ersten 104 Stellen von π (das läuft schnell):

,1([:}.'0123456789abcdef'{~[:|.[:<.[:(],~16*1|{.)^:8 d)"0\8*i.13x

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89
452821e638d01377be5466cf34e90c6cc0ac29b7

Warum verwenden Sie nicht #:, um die Zahlen in Hexadezimalzahlen umzuwandeln?
FUZxxl

Ich bin mir nicht sicher was du meinst. #:gibt keine hexadezimalen Ziffern aus.
Eelvex

IMHO ist es einfacher, #: und eine Umformung zu verwenden, um hexadezimale Zahlen zu generieren, als Ihr aktueller Ansatz.
FUZxxl

Du meinst so etwas wie (... 16 #:) Pi? Ich denke, wir haben nicht genug Ziffern, also müssen wir sie trotzdem generieren.
Eelvex

1
Übrigens habe ich herausgefunden, dass es das Verb gibt hfd, um Zahlen in Hexadezimalzahlen umzuwandeln.
FUZxxl

5

JavaScript, 536

(Zeilenumbrüche und Einrückungen nur zur besseren Lesbarkeit)

var d='0123456789abcdef',p='',o='',l=3e3,c=0,e='length';d=d+d;
function $(n,r){return n[e]<=r?0:d.indexOf(n[r])}
function g(a,b){for(i=0,t='',s=16;i<l;i++,t+=d[~~(s/b)],s=(s%b)*16);
for(;a--;t=_(t,t,1));return t}
function _(a,b,s){for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i>=0;r=(s?
  function(k){c=k>15;return d[k]}($(a,i)+$(b,i)+c):
  function(k){c=k<0;return d[k+16]}($(a,i)-$(b,i)-c))+r,i--);return r}
for(i=0;i<l;i++,p+='2');
for(j=1;j<l;p=_(p,(o+='0')+_(_(_(g(2,8*j+1),g(1,8*j+4)),g(0,8*j+5)),g(0,8*j+6)),1),j++);
console.log(p.slice(1024,2048))

Auf meinem Laptop mit Intel i5 Core dauert es bei Google Chrome 14 ungefähr 25 Sekunden. Kann jemand anderen diesen Code Golf spielen? Ich kann nicht gut golfen .. :(

Unten ist nicht golfen. Ich entferne einfach alle Kommentare und wechsle für die Schleife zum Golfen.

Erwähne nichts über for(;s>=b;s-=b);s*=16;. Ich habe es in geändert s=(s%b)*16. : P

/**
Calculate PI-3 to 3000 (3e3) digits.
a : a
b : b
c : carry
d : digits
e : length
f : get from d
g : calculate (2^a)/b.
i,j, : for looping
l : length to calculate
p : pi
r,t : return value
*/
var d='0123456789abcdef',p='',o='',l=3e3,c=0,e='length';
d=d+d;//for carring

function $(n,r){return n[e]<=r?0:d.indexOf(n[r])}
/*
Calculate (2^a)/b. Assume that 2^a < b.
*/
function g(a,b){
    for(i=0,t='',s=16;i<l;i++){t+=d[~~(s/b)];for(;s>=b;s-=b);s*=16;}
    for(;a--;t=_(t,t,1));return t}
/*
Calculate a±b. (+ when s=1, - when s=0) When calculating minus, assume that 1>b>a>0.
*/
function _(a,b,s){
    for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i>=0;
        r=(s?function(k){c=k>15;return d[k]}($(a,i)+$(b,i)+c):
            function(k){c=k<0;return d[k+16]}($(a,i)-$(b,i)-c))+r,i--);return r;
}
/*
Using BBP formula. Calc when j=0...
4/1 - 2/4 - 1/5 - 1/6 = 3.22222222.... (b16)
*/
for(i=0;i<l;i++,p+='2');
//Calc when j>0
for(j=1;j<l;p=_(p,(o+='0')+_(_(_(g(2,8*j+1),g(1,8*j+4)),g(0,8*j+5)),g(0,8*j+6)),1),j++);
console.log(p.slice(1024,2048));

BEARBEITEN: Völlig unbenutzte Funktion entfernt. (Warum habe ich das behalten?: /)

PS. Erste 100 Stellen von PI

243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be5466cf34e90c6cc0ab


@FUZxxl: War der Code ohne Golf nicht genug? .. :(
JiminP

Es war in der Tat. Aber meiner Meinung nach sieht es besser aus, wenn Sie die Code-Formatierung anstelle der Backtick-Syntax verwenden. Wie ich geschrieben habe, können Sie jederzeit zurückkehren, wenn Sie dies nicht mögen.
FUZxxl

d='0123456789abcdef',l=3e3,p=Array(l+1).join(2),o='',c=0,e='length';d+=d;function _(a,b,s){for(i=(a[e]>b[e]?a[e]:b[e])-1,r='',c=0;i+1;r=d[Z=F(b,i,1)+c,k=F(a,i,1)+(s?Z:16-Z),c=s?k>15:k<16,k]+r,i--);return r}function F(a,b,f){if(f)f=a[e]>b?d.indexOf(a[b]):0;else{for(i=0,f='',s=16;i++<l;f+=d[~~(s/b)],s=(s%b)*16);while(a--)f=_(f,f,1)}return f}for(j=0;++j<l;p=_(p,(o+='0')+_(_(_(F(2,z=8*j+1),F(1,z+3)),F(0,z+4)),F(0,z+5)),1));console.log(p.slice(1024,2048))
Peter Taylor

Das sind wirklich alle Mikrooptimierungen, obwohl einige von ihnen ziemlich groß aussehen. Die größte Ersparnis ergibt sich aus der Beseitigung der beiden anonymen Funktionen _zugunsten des ,Betreibers. Das schwierigste ist das Zusammenführen von $und gzu einer Funktion mit einem optionalen Argument zur Auswahl. functionund returnsind beide ziemlich teuer, so ist ein if(f)...elseund ein paar ,1ein vernünftiger Kompromiss.
Peter Taylor

4

PHP 116 114 Bytes

<?for(;$g?$d=0|($$g=$g--/2*$d+($$g?:2)%$g*$f)/$g--:4613^printf($i++>257?'%04x':'',$e+$d/$f=4*$g=16384)^$e=$d%$f;);

Diese Lösung berechnet alle pi bis zu 2048 Hexadezimalstellen, jeweils vier Hexadezimalstellen, und gibt die letzte Hälfte davon aus. Die Ausführungszeit beträgt weniger als 5 Sekunden. Die für die Berechnung verwendete Formel lautet wie folgt:

pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + 5/11*(2 + 6/13*(2 + 7/15*(2 + ... )))))))

Die Genauigkeit wird erhalten, indem die Reste in einem Array gespeichert und jede der 2 ^ 14 Unterteilungen inkrementell fortgesetzt werden.

Python 64 Bytes

x=p=16385
while~-p:x=p/2*x/p+2*2**8192;p-=2
print('%x'%x)[1025:]

Gleiche Methode wie oben. Läuft in ca. 0,2s.

Oder als Einzeiler in 73 Bytes :

print('%x'%reduce(lambda x,p:p/2*x/p+2*2**8192,range(16387,1,-2)))[1025:]

3

PARI / GP-2.4, 141

forstep(d=1024,2047,8,y=frac(apply(x->sum(k=0,d+30,16^(d-k)/(8*k+x)),[1,4,5,6])*[4,-2,-1,-1]~);for(i=0,7,y=16*frac(y);printf("%X",floor(y))))

Natürlich mit der Bailey-Borwein-Plouffe-Formel.

Läuft in weniger als einer Minute.


3

C-Code:

long ki,k,e,d=1024;
int  dig,tD=0,c,Co=0,j,js[4]  ={1,4,5,6};
double res=0.0,tres=0.0,gT,ans[4] ={0.0};
while(tD < 1024)
{while(Co<4){ j= js[Co],gT=0.0,ki= 0;
 for(; ki < d+1;ki++){ k = 8*ki+j,e= d-ki,c=1; while(e--) c = 16*c % k; gT+=((double)(c)/(double)k);}
 ans[Co] = (gT - (int)gT),++Co;}
 double gA = 4*ans[0]-2*ans[1]-ans[2]-ans[3];
 gA = (gA<0) ? gA + -1*(int)gA +1 : gA -(int)gA;
 dig=0;while(dig++ < 6 && tD++ < 1024) gA *=16, printf("%X",gA),gA -= (int)gA;
 d+=6,Co = 0;}

Laufzeit = 8,06 Sekunden auf einem Intel Quad Core


Das ist Code Golf. Versuchen Sie, Ihren Code so weit wie möglich zu komprimieren, indem Sie kurze Variablennamen verwenden und Leerzeichen vermeiden. Zum Beispiel könnten Sie eine Menge Zeichen sparen, indem Sie printf("%X",(int)gA)anstelle dieser langen Liste verwenden.
FUZxxl

1

PARI / GP - 40 Bytes

Diese Version 'betrügt', indem sie verwendet wird \x, um die hexadezimalen Ziffern des Ergebnisses anzuzeigen.

\p8197
x=Pi<<4^6;x-=x\1;x=(x<<4^6)\1
\xx

Diese Version benötigt 87 Bytes, um auf die übliche Weise in Hexadezimal umzuwandeln.

\p8197
x=Pi<<4^6;x-=x\1;concat([Vec("0123456789abcdef")[n+1]|n<-digits((x<<4^6)\1,16)])

Beide Versionen laufen im Bruchteil einer Sekunde.


1

Perl - 59

use ntheory"Pi";say substr int(Pi(3000)<<8192)->as_hex,1027

Weniger als 0,1 s.


0

Schale 68

Werkzeuge: bc -l, tr, cut

echo "scale=2468;obase=16;4*a(1)"|bc -l|tr -d '\\\n'|cut -c1027-2051

Shell 64, tools: bc -l, tr, tail, unterscheidet sich in der Rundung der letzten Stelle

echo "scale=2466;obase=16;4*a(1)"|bc -l|tr -d '\\\n'|tail -c1024

Könnte als Betrug betrachtet werden, da das Wissen, wie man PI berechnet, in 4 * a (1) ist und dass 1 scale = 2466 verwendet werden muss, iterativ untersucht wurde.

Danke an breadbox für die Idee, cut zu verwenden.


Ich verstehe nicht, wie das als Betrug angesehen werden könnte. Die Ziffern werden zur Laufzeit berechnet. Obwohl ich beachten sollte, dass sich die Ausgabe bei der letzten Ziffer (7 anstelle von A) unterscheidet, wenn ich sie ausführe. BTW, ich denke, Sie können den ddBefehl durch ersetzen tail -c1024, um ein paar Zeichen zu sparen.
Brotkasten

Ja, ich habe den Unterschied auch beobachtet (und eine halbe Stunde damit verbracht :)). Wenn ich bc anweise, eine Skala mit x Ziffern zu verwenden, wird im Dezimalmodus auf diese Ziffer gerundet und anschließend eine Hexadezimalumwandlung durchgeführt. Wenn ich also eine weitere Ziffer nehme, ergibt sich eine 69, keine 7. Allerdings wurde in der Frage weder ein Rundungsstil noch eine Kürzung angegeben. Und danke für die Schwanzidee. :)
Benutzer unbekannt

Die Frage lautet: Beenden und Erzeugen einer Ausgabe, die mit der angegebenen identisch ist.
FUZxxl,

@FUZxxl: "sollte ...", nicht "muss ..." - Ich dachte, es sollte hilfreich sein, zu überprüfen, ob die Hex-Konvertierung gut funktioniert, und die Anzahl der zu überspringenden Zeichen nicht als Teil der Spezifikation Aber ich gab nach und fügte 16 Zeichen hinzu, um eines zu ersetzen.
Benutzer unbekannt

1
Da der Satz mit dem Wort "Formal" beginnt, würde ich zustimmen, dass das OP es wahrscheinlich im RFC-Sinne des Wortes meinte . Auch können Sie Ihre neue Lösung verbessern , indem die Verwendung von Ersatz ddmit cut -c1027-2051. (Die Shell verfügt über zahlreiche Tools zum Bearbeiten von Textströmen.)
breadbox
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.