Yksi nopeimmista algoritmeista piin laskemiseen saadaan tästä sarjasta: https://petke.info/piisarja.jpg
Vaan kuinka nopeasti eri ohjelmointikielillä saadaan laskettua piin kuusitoista (- tai Pythonilla jopa 28) ensimmäistä oikeaa merkitsevää numeroa tuolla sarjakehitelmällä? Koodissani myös tulostetaan jokaisessa vaiheessa laskettu pii ja indeksi... Itse en valitettavasti osaa asentaa kirjastoja, joilla laskisi useamman desimaalin tarkkuudella piitä, kuin mitä peruskieli antaa.
Red-kieli:
red[] potenssi: func[a b][ luku: 1.0 loop b [ luku: luku * a ] return luku ] print "Odota..." aika1: now/precise pii: 0 ind: 1 piiapu1: 0 piiapu2: 0 while [pii <> pi][ piiapu1: piiapu1 + (4 / (ind * (potenssi 5 ind))) piiapu2: piiapu2 - (1 / (ind * (potenssi 239 ind))) ind: ind + 2 piiapu1: piiapu1 - (4 / (ind * (potenssi 5 ind))) piiapu2: piiapu2 + (1 / (ind * (potenssi 239 ind))) pii: 4 * (piiapu1 + piiapu2) print pii ind: ind + 2 ] aika2: now/precise print difference aika2 aika1 halt
Tulostaa:
E:\Tiede\pii>pii.exe
Odota...
3.14059702932606
3.141591772182177
3.141592652615309
3.141592653588603
3.141592653589792
0:00:00.023
Eli 23 sadasosa sekuntia 16 ensimmäistä oikeaa desimaalia.
REBOL-kieli (täsmälleen sama koodi - Red-kieli on kehittyneempi versio REBOL:sta):
Tätä ihmettelen!
Odota...
3 3.14059702932606
7 3.14159177218218
11 3.14159265261531
15 3.1415926535886
19 3.14159265358979
0:00:00.011
>>
REBOL-koodi laski 15 ensimmäistä merkitsevää numeroa melkein puolet nopeammin, kuin Red-kieli! Jotain ymmärrän ohjelmointikielistä väärin, sillä REBOL-koodi on tulkkaava kun taas Red-kielen koodin ajoin käännetyllä .exe tiedostolla.
(No höpö höpö! En tiedä, mikä oli mennyt pieleen ja hidastanut konetta ensimäisessä Red-kielen ajossa - uusinta-ajo antoi nopeudeksi:
E:\Tiede\pii>pii.exe
Odota...
3 3.14059702932606
7 3.141591772182177
11 3.141592652615309
15 3.141592653588603
19 3.141592653589792
0:00:00.01
Eli yhden sadasosa sekunnin).
Ohjelmoidaanpa sama sarjakehitelmä vielä Pythonille:
import math from decimal import Decimal ind = Decimal(1) pii = Decimal(0) piiapu1 = Decimal(0) piiapu2 = Decimal(0) while Decimal(pii) != Decimal(math.pi): jakaja = Decimal(ind) * Decimal(math.pow(5,ind)) piiapu1 = Decimal(piiapu1) + (4/Decimal(jakaja)) jakaja = Decimal(ind) * Decimal(math.pow(239, ind)) piiapu2 = Decimal(piiapu2) - (1/(Decimal(jakaja))) ind = Decimal(ind) + 2 jakaja = Decimal(ind) * Decimal(math.pow(5,ind)) piiapu1 = Decimal(piiapu1) - (4/Decimal(jakaja)) jakaja = Decimal(ind) * Decimal(math.pow(239, ind)) piiapu2 = Decimal(piiapu2) + (1 / (Decimal(jakaja))) pii = 4 * (Decimal(piiapu1) + (Decimal(piiapu2))) print(ind,pii) ind = Decimal(ind) + 2
Tulostus:
3 3.140597029326060314304531106
7 3.141591772182177295018212291
11 3.141592652615308608149350748
15 3.141592653588602228662171260
19 3.141592653589791696917279619
23 3.141592653589793236391840944
27 3.141592653589793238459788160
31 3.141592653589793238462639369
35 3.141592653589793238462643376
39 3.141592653589793238462643382
En nyt osannut Pythonilla ottaa aikaa, kauan se laski nuo 28 desimaalia oikein :( Olisi vaatinut "Import Time" -kirjastoa kai, mutta kun ei löytynyt sellaista...
Kiinnostaisi vielä tietää, että kuinka kaun menee C-kielellä. En kyllä osaa tähän hätiin ohjelmoida sitä :( Pascalin voisin vielä ohjelmoida jossain välissä. En tiedä kyllä osaanko sillekään ottaa aikaa. Käsittääkseni C-kieli tuottaa ylivoimaisesti "koneenläheisimpää" koodia ja on nopein? Olisi tosi kiva, jos joku C-kielen taitaja voisi koodailla :) Ja osaisi vielä mitata ajon aikaa.
Linukassa voi suoritusajan mitata time-ohjelmalla, mutta toi pi:n laskenta-algoritmi on sen verran nopea, että sillä ei saada järkeviä arvoja edes pythonilla.
import math from decimal import Decimal ind = Decimal(1) pii = Decimal(0) piiapu1 = Decimal(0) piiapu2 = Decimal(0) print (Decimal(math.pi)) print (math.pi) xpii=Decimal(1) while Decimal(pii) != Decimal(xpii): xpii=pii jakaja = Decimal(ind) * Decimal(math.pow(5,ind)) piiapu1 = Decimal(piiapu1) + (4/Decimal(jakaja)) jakaja = Decimal(ind) * Decimal(math.pow(239, ind)) piiapu2 = Decimal(piiapu2) - (1/(Decimal(jakaja))) ind = Decimal(ind) + 2 jakaja = Decimal(ind) * Decimal(math.pow(5,ind)) piiapu1 = Decimal(piiapu1) - (4/Decimal(jakaja)) jakaja = Decimal(ind) * Decimal(math.pow(239, ind)) piiapu2 = Decimal(piiapu2) + (1 / (Decimal(jakaja))) pii = 4 * (Decimal(piiapu1) + (Decimal(piiapu2))) print(ind,pii) ind = Decimal(ind) + 2
$ time python3 piitesti.py 3.141592653589793115997963468544185161590576171875 3.141592653589793 3 3.140597029326060314304531106 7 3.141591772182177295018212291 11 3.141592652615308608149350748 15 3.141592653588602228662171260 19 3.141592653589791696917279619 23 3.141592653589793236391840944 27 3.141592653589793238459788160 31 3.141592653589793238462639369 35 3.141592653589793238462643376 39 3.141592653589793238462643382 43 3.141592653589793238462643382 real 0m0,022s user 0m0,022s sys 0m0,000s
#include <math.h> #include <iostream> #include <iomanip> using namespace std; int main () { long double ind = (1); long double pii = (0); long double piiapu1 = (0); long double piiapu2 = (0); long double jakaja; long double xpi=1; while (xpi!=pii) { xpi=pii; jakaja = (ind) * (pow(5,ind)); piiapu1 = (piiapu1) + (4/(jakaja)); jakaja = (ind) * (pow(239, ind)); piiapu2 = (piiapu2) - (1/((jakaja))); ind = (ind) + 2; jakaja = (ind) * (pow(5,ind)); piiapu1 = (piiapu1) - (4/(jakaja)); jakaja = (ind) * (pow(239, ind)); piiapu2 = (piiapu2) + (1 / ((jakaja))); pii = 4 * ((piiapu1) + ((piiapu2))); cout << setprecision(30) << ind << " " << pii << "\n"; ind = (ind) + 2; } }
$ time ./pii 3 3.1405970293260603142665443599 7 3.14159177218217729502490465077 11 3.14159265261530860815358812133 15 3.14159265358860222876538625947 19 3.14159265358979169699416011952 23 3.14159265358979323656124504893 27 3.1415926535897932387296493939 31 3.1415926535897932387296493939 real 0m0,002s user 0m0,002s sys 0m0,000s
Jossain vaiheessahan noita piin desimaalien laskemisia käytettiin tietokoneiden suorituskyvyn mittaamiseen ylikellottelupiireissä.
Itse kokeilin huvikseni kauanko omalla koneellani kestää laskea puoli miljardia desimaalia y-cruncherilla, joka käyttää Tšudnovskin algortimia vuodelta 1988.
Siinä on myös mahdollista käyttää Ramanujanin algoritmia vuodelta 1910, joka on noin 40% hitaampi.
lainaus:
Total Computation Time: 31.658 seconds ( 0.528 minutes )
Start-to-End Wall Time: 33.581 seconds ( 0.560 minutes )CPU Utilization: 992.59 % + 3.06 % kernel overhead
Multi-core Efficiency: 82.72 % + 0.26 % kernel overheadLast Decimal Digits: Pi
3896531789 0364496761 5664275325 5483742003 7847987772 : 499,999,950
5002477883 0364214864 5906800532 7052368734 3293261427 : 500,000,000
Eli puolisen minuuttia meni 500 000 000 piin desimaalin laskemiseen.
Laskuvauhti oli siis luokkaa 2µs / 28 desimaalia.
PetriKeckman kirjoitti:
Yksi nopeimmista algoritmeista piin laskemiseen saadaan tästä sarjasta: https://petke.info/piisarja.jpg
Onko tuolle algortimille jotain nimeä? Olisi kiva tietää kuinka nopea se on suhteessa vaikka Tšudnovskin algoritmiin nähden.
Grez kirjoitti:
Onko tuolle algortimille jotain nimeä? Olisi kiva tietää kuinka nopea se on suhteessa vaikka Tšudnovskin algoritmiin nähden.
Taitaa olla sellaisen herran kuin John Machin kehitelmä, eli Machin:in kaava.
Jos isot luvut ovat tuettuna, niin esimerkiksi 8th:lla voin käyttää "big float" lukuja ja kirjoittaa yksinkertaisesti:
: pi \ n -- n dup ## n:1+ n# F1 F5 n:/ n:atan F4 n:* F1 F239 n:/ n:atan n:- F4 n:* ; : app:main 1000 pi . cr bye ;
Ja ajettaessa ohjelma tulostaa piin 1000 ensimmäistä desimaalia:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
Et kuitenkaan ottanut ylös aikaa, että montako mikrosekuntia tuon rouskuttamiseen kului.
Mutta kukapa noita tietokoneella laskisi https://www.youtube.com/watch?v=CKl1B8y4qXw :D
Grez kirjoitti:
Et kuitenkaan ottanut ylös aikaa, että montako mikrosekuntia tuon rouskuttamiseen kului.
Raspberry Pi 4B:llä ajettuna ja time tulostus:
real 0m0.190s user 0m0.164s sys 0m0.017s
Mikä on käytännössä melkein sama aika, jos suorittaisin tyhjän ohjelman...
Juu täytyis varmaan laskea muutama kertaluokka enemmän kuin 1000 desimaalia että voisi arvioida tehokkuutta.
Grez kirjoitti:
Jos isot luvut ovat tuettuna, niin esimerkiksi 8th:lla voin käyttää "big float" lukuja ja kirjoittaa yksinkertaisesti:
: pi \ n -- n dup ## n:1+ n# F1 F5 n:/ n:atan F4 n:* F1 F239 n:/ n:atan n:- F4 n:* ; : app:main 1000 pi . cr bye ;
Eikö paljon yksinkertaisempaa olisi kirjoittaa vaan n:PI?
Alkuperäinen ideahan on tietenkin, että lasketaan ilman valmista trigonometriakirjastoa, mutta jos sellaista "saa käyttää" niin sieltä löytyy yleensä (kuten tässäkin tapauksessa) pii myös suoraan.
Grez kirjoitti:
Eikö paljon yksinkertaisempaa olisi kirjoittaa vaan n:PI?
Alkuperäinen ideahan on tietenkin, että lasketaan ilman valmista trigonometriakirjastoa, mutta jos sellaista "saa käyttää" niin sieltä löytyy yleenä (kuten tässäkin tapauksessa) pii myös suoraan.
Yleensähän tuo kirjastossa oleva taitaa olla määritelty vakio ja rajoitettu tietylle tarkkuudelle. Näyttäisi 8th:lla olevan isoja lukuja käytettäessä 130 desimaalia. Tuo laittamani koodi taas laskee halutulla tarkkuudella.
(Mod. siirsi toisesta keskustelusta.)
PetriKeckman kirjoitti:
Hah hahhaa! :) :) Paitsi, että jos aioit opiskella vain kymmenen ensimmäistä desimaalia, ...
Näitä on helppo ja kohtuullisen nopea laskea käyttäen suoraan Machin kaavaa, mikäli ohjelmointikieli mitä käyttää tukee isoja lukuja:
: pi \ n -- n dup ## n:1+ n# F1 F5 n:/ n:atan F4 n:* F1 F239 n:/ n:atan n:- F4 n:* ; : app:main 0 args 1000 ?: >n pi . cr ;
Alla 1000 ensimmäistä desimaalia
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
Sulla on hieno kieli käytössä, kun noin lyhyellä koodin pätkällä saat aikaiseksi. Ei välttämättä kuitenkaan ehkä kovin luettavaa (IMO).
Panin Pythonilla kahdella paremmaksi ;) Laskin samalla Machin kaavalla 500 askelta ja laskut viidentuhannen desimaalin tarkkuudella ja sain ainakin tuolla https://decimal.info/digits-of-pi/value-of-pi-to-1000-decimal-places.html olevan luvun perusteella oikein desimaalit 990 - 1000. Eli eiköhän se tuhannesensimmäinen ja tuhannestoinenkin ole oikea.
# Import math Library import math from decimal import Decimal from decimal import Decimal, getcontext import math from datetime import datetime import mp import mpmath as mpmath getcontext().prec = 50000 mpmath.mp.dps = 50000 now1 = datetime.now() ind = mpmath.mpf(1) pii = mpmath.mpf(0) piiapu1 = mpmath.mpf(0) piiapu2 = mpmath.mpf(0) for kierroksia in range (1,500): jakaja = mpmath.mpf(ind) * mpmath.mpf(pow(5,ind)) piiapu1 = mpmath.mpf(piiapu1) + (4/mpmath.mpf(jakaja)) jakaja = mpmath.mpf(ind) * mpmath.mpf(pow(239, ind)) piiapu2 = mpmath.mpf(piiapu2) - (1/(mpmath.mpf(jakaja))) ind = mpmath.mpf(ind) + 2 jakaja = mpmath.mpf(ind) * mpmath.mpf(pow(5,ind)) piiapu1 = mpmath.mpf(piiapu1) - (4/mpmath.mpf(jakaja)) jakaja = mpmath.mpf(ind) * mpmath.mpf(pow(239, ind)) piiapu2 = mpmath.mpf(piiapu2) + (1 / (mpmath.mpf(jakaja))) pii = 4 * (mpmath.mpf(piiapu1) + (mpmath.mpf(piiapu2))) ind = mpmath.mpf(ind) + 2 now2=datetime.now() ero=now2-now1 print(ero) print(str(pii)[900:1004])
tuloste kirjoitti:
0:00:02.248266
035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164 20198938 Process finished with exit code 0
PetriKeckman kirjoitti:
Sulla on hieno kieli käytössä, kun noin lyhyellä koodin pätkällä saat aikaiseksi. Ei välttämättä kuitenkaan ehkä kovin luettavaa (IMO).
Panin Pythonilla kahdella paremmaksi ;) Laskin samalla Machin kaavalla 500 askelta ja laskut viidentuhannen desimaalin tarkkuudella ja sain ainakin tuolla https://decimal.info/digits-of-pi/value-of-pi-to-1000-decimal-places.html olevan luvun perusteella oikein desimaalit 990 - 1000. Eli eiköhän se tuhannesensimmäinen ja tuhannestoinenkin ole oikea.
Miksi ihmeessä et anna isojen lukujen kirjaston tehdä sitä mihin se on tarkoitettu? Kokeilepa alla olevaa versiota piruuttasi laskemaan ensimmäiset 5000 desimaalia. En keksinyt, miten Pythonilla voi laskea suuremmalla tarkkuudella ja tulostaa vähemmän desimaaleja käsittelemättä lukua merkkijonona ettei tulisi pyöristysvirhettä viimeisen halutun desimaalin kohdalla.
import mpmath from mpmath import mpf as mpf mpmath.mp.dps=5002 pi=((mpmath.atan((mpf(1)/mpf(5)))*mpf(4)-mpmath.atan((mpf(1)/mpf(239))))*mpf(4)) print(str(pi) [:5002])
jalski kirjoitti:
Miksi ihmeessä et anna isojen lukujen kirjaston tehdä sitä mihin se on tarkoitettu?
Ei oo nättiä laskea piitä isojen lukujen kirjastojen atan funktiolla :) Sehän olisi melkein sama kuin jos suorittaisi käskyn "PRINT pi" ja kuvittelisi laskeneensa piille arvoa.
En ymmärrä sitä mitä et keksinyt :) Sori, vika on mun päässä. Tiedät nimittäin varmasti miten Pythonilla voi tulostaa vähemmän desimaaleja:
print(str(pii)[900:1004])
Tulostaa lasketun piin desimaalit 900:stä 1004:een.
En oo ohjelmoija, olen algoritminen taiteilija, siksi mun on vaikea pysyä välillä kärryillä täällä putkan keskusteluissa.
PetriKeckman kirjoitti:
Ei oo nättiä laskea piitä isojen lukujen kirjastojen atan funktiolla :) Sehän olisi melkein sama kuin jos suorittaisi käskyn "PRINT pi" ja kuvittelisi laskeneensa piille arvoa.
En ymmärrä sitä mitä et keksinyt :) Sori, vika on mun päässä. Tiedät nimittäin varmasti miten Pythonilla voi tulostaa vähemmän desimaaleja:
print(str(pii)[900:1004])Tulostaa lasketun piin desimaalit 900:stä 1004:een.
Tuo kirjastossa oleva on kuitenkin todennäköisesti vain tallennettu vakio, laskemalla saat halutun määrän desimaaleja.
EDIT: Näköjään mpmath kirjastossa tuo pi ei olekaan pelkkä tallennettu vakio.
Sitä paisi, koodisi suoritusaika oli omalla RPI 4B tietokoneellani yli 12 sekuntia. Laittamani versio laskee ja tulostaa 5000 desimaalia 0,278 sekunnissa.
Meinasin sitä, että pystyykö Pythonilla asettamaan lukujen laskentatarkkuuden ja esitystarkkuuden erikseen? Tokihan tuon sopivan määrän desimaaleja tulostaminen onnistuu käsittelemällä lukua merkkijonona.
jalski kirjoitti:
EDIT: Näköjään mpmath kirjastossa tuo pi ei olekaan pelkkä tallennettu vakio.
Joo, ei. Piistä voi tuottaa 5000 ensimäistä desimaalia sillä tällee:
# Import math Library import math from decimal import Decimal from decimal import Decimal, getcontext import math from datetime import datetime import mp import mpmath as mpmath getcontext().prec = 50000 mpmath.mp.dps = 50000 now1 = datetime.now() print(mpmath.pi); now2=datetime.now() ero=now2-now1 print(ero)
Aikaa meni 0:00:00.153061. Vähän hämäräperäinen aikamerkintä. Oisko tuo 0.153... sekuntia?
Yleensä ollaan kiinnostuneita vain nopeimmista tavoista tuottaa pii, mutta olen nyt kiinnostunut yhdestä hitaiten suppenevimmista sarjasta. Se on Gregory–Leibniz-sarja. Sarja on minusta kaunis, yksinkertainen ja siksi se kiehtoo. Nelosta jaetaan parittomilla luvuilla ja vuoroin summataan, vuoroin vähennetään.
Kts: https://petke.info/leibniz.jpg
Tutkitaanpa REBOL:lla, Red:llä, Pythonilla ja Pascalilla kuinka kauan kestää, että saadaan 8 desimaalia oikein. Tämä on samalla siis myös mielenkiintoinen tehokkuustesti eri kielille. Toki suoritusnopeuteen vaikuttanee kai myös se mitä muita ohjelmia on käytössä samaan aikaan, kun ei sitä nyt jaksa olla tekemättä mitään ja odottaa ajon valmistumista.
REBOL:lla kesti niin kauan - lähes kahdeksan minuuttia ja termejä tarvittiin huimat yli kymmenen miljoonaa, että meinasin jo keskyttää ajon ja vähentää vaadittavien oikeitten desimaalien määrää. REBOL ei ole tehokas, mutta se on hyvin dokumentoitu ja olen tottunut sitä käyttämään, siksi se on minulle luontevin kieli algoritmista taidettani tuottaessani.
Aloitettiin siis REBOL:lla
rebol[] print "odota" aika1: now/precise indeksi: 0 pii: 0.0 jakaja: 1.0 virhe: 0.000000001 ;hyväksyttävä virhe while [(abs (pii - pi)) > virhe][ pii: pii + (4 / jakaja) jakaja: jakaja + 2 pii: pii - (4 / jakaja) jakaja: jakaja + 2 indeksi: indeksi + 2 ] aika2: now/precise print difference aika2 aika1 print indeksi print pii print pi halt
REBOLin tuloste kirjoitti:
odota
0:07:57.329
1001758378
3.14159265258979
3.14159265358979
>>
Sitten Red
(syntaksiltaan sama kuin REBOL, paitsi että ei näyttänyt abs funktiota hyväksyneen)
red[] print "odota" aika1: now/precise indeksi: 0 pii: 0.0 jakaja: 1.0 virhe: 0.000000001 ;hyväksyttävä virhe while [(absolute (pii - pi)) > virhe][ pii: pii + (4 / jakaja) jakaja: jakaja + 2 pii: pii - (4 / jakaja) jakaja: jakaja + 2 indeksi: indeksi + 2 ] aika2: now/precise print difference aika2 aika1 print indeksi print pii print pi halt
Red tulosti kirjoitti:
E:\Tiede\piisarjat>1.exe
odota
0:09:17.767
1001915718
3.141592652589794
3.141592653589793
Nyt en ymmärrä! Redin .exe tiedosto näyttää olevan hitaampi kuin REBOL:n tulkattava kieli :O Ja tässä se kuinka monta termiä joudutaan ottamaan on eri luku kuin REBOL:ssa. No, mennään eteen päin...
Sitten Pyhon
# Import math Library import math from datetime import datetime pii=0.0 jakaja=1.0 indeksi=1 virhe = 0.000000001 now1 = datetime.now() while abs(pii - math.pi) > virhe: pii=pii+(4/jakaja) jakaja=jakaja+2 pii=pii - (4/jakaja) jakaja=jakaja+2 indeksi=indeksi+2 now2=datetime.now() ero=now2-now1 print(ero) print (indeksi) print(pii) print(math(pi))
Python tulosti kirjoitti:
C:\Python39\python.exe E:/Tiede/pii/tarkkuuslaskuri.py
0:03:58.729484
1001758379
3.1415926525897935
3.141592653589793Process finished with exit code 0
Python onkin sitten yli puolet nopeampi.
Ja lopuksi Pascal
Program Leipniz; uses Crt, sysutils; VAR pii, virhe : Real; jakaja, indeksi : Longint; now1, now2 : TDateTime; begin pii:=0; jakaja:=1; indeksi:=1; virhe:=0.000000001; now1:=Now; WHILE abs(pii - Pi) > virhe DO BEGIN pii:= pii + (4 / jakaja); jakaja:= jakaja + 2; pii:= pii - (4 / jakaja); jakaja:= jakaja + 2; indeksi:= indeksi + 2; END; now2:=Now; WRITELN(now2-now1); WRITELN(indeksi); WRITELN(pii); WRITELN(Pi); end.
Pascal tulosti kirjoitti:
C:\FPC\3.2.0\bin\i386-win32>pii
2.5300927518401295E-005
1001919509
3.1415926525897935E+000
3.14159265358979323851E+0000
Ylivoimaisesti nopein! 2.5 sekuntia. Minä alan käyttämään vanhaa kunnon Pascalia kaikessa muussa ohjelmoinnissa paitsi algoritmisessa taiteessa.
Joo ...
Pascalin kulta-aikoina ei ollut resursseja tuhlattavaksi, joten kääntäjäkin tuli optimoitua kunnolla.
Jos nopeutta haluaa, niin sopivia kieliä ovat Assembler, C/C++, Rust ja Pascal. Joku guru voi täydentää listaa.
Edit - Huomioi myös, että esittämissäsi ratkaisuissa muissa kuin Pascalissa ei esitellä muuttujien tyyppejä. Luulisi senkin vaikuttavan nopeuteen, kun muuttujan tyyppi ei ole any.
peran kirjoitti:
Jos nopeutta haluaa, niin sopivia kieliä ovat Assembler,...
Voin olla väärässä, mutta minusta listasi ensimmäistä eli Assembleria ei voida sanoa edes ohjelmointikieleksi. Siinähän ohjelmoija joutuu käskyttämään konetta itse aivan konekielen tasolla ja eikös ole niin, että kehittyneet kääntäjät optimoivat koodia kehittyneemmin kuin mitä ihminen pystyy tekemään? Näin siis ainakin vähänkin monimutkaisempien ohjelmien osalta kuin esimerkisi tapauksen, missä on pelkkä silmukka muuttujalle 1-10000. Tällöin ihminen varmasti pystyy Assemblerilla tekemään yhtä tehokkaan ohjelman kuin kääntäjä.
Yllättävän hyvin muuten pärjäsi myös FreeBasic. Alle 5 sekuntia.
Dim Time1 as Double Dim Time2 as Double Dim pii as Double Dim pi as Double dim virhe as Double Dim jakaja as Integer Dim indeksi as Integer pi = 3.1415926535897932 pii=0 jakaja=1 indeksi=1 virhe=0.000000001 Time1 = Timer While (abs(pii - Pi) > virhe) pii= pii + (4 / jakaja) jakaja= jakaja + 2 pii= pii - (4 / jakaja) jakaja= jakaja + 2 indeksi= indeksi + 2 Wend Time2 = Timer Print Time2 - Time1 Print indeksi Print pii Print pi End
FreeBasic tulosti kirjoitti:
E:\freebasic\free>pii
4.667424999992363
1001758379
3.141592652589794
3.141592653589793
Hyvä tulos voi ehkä johtua osittain siitä, että minulla on pi siinä vakioarvoinen muuttuja ja kuten tässä keskustelussa ollaan todettu, niin ainakin esimerksi Pythonissa pii ei ole talletettu vakio, vaan kone ehkä laskee sen arvon aina uudestaan? En alkanut tutkimaan, kuinka FreeBasicciin asennettaisiin jokin matemaattinen kirjasto, mikä kai pitäisi tehdä, jotta piitä voitaisiin siinä käyttää vakiona.
EDIT: Tarkoitus oli lisätä tää edelliseen viestiin, mutta tuli nyt vahingossa uusi viesti.
peran kirjoitti:
Edit - Huomioi myös, että esittämissäsi ratkaisuissa muissa kuin Pascalissa ei esitellä muuttujien tyyppejä.
Jaa, ainakaan REBOL:ssa ei voida edes esitellä luvuille tyyppejä. Muuttuja luku: 1.0 on float, koska siinä on desimaalipiste ja luku: 1 on Integer. Tyypit siis päätellään arvon sijoituksessa.
PetriKeckman kirjoitti:
peran kirjoitti:
Jos nopeutta haluaa, niin sopivia kieliä ovat Assembler,...
Voin olla väärässä, mutta minusta listasi ensimmäistä eli Assembleria ei voida sanoa edes ohjelmointikieleksi. Siinähän ohjelmoija joutuu käskyttämään konetta itse aivan konekielen tasolla ja eikös ole niin, että kehittyneet kääntäjät optimoivat koodia kehittyneemmin kuin mitä ihminen pystyy tekemään? Näin siis ainakin vähänkin monimutkaisempien ohjelmien osalta kuin esimerkisi tapauksen, missä on pelkkä silmukka muuttujalle 1-10000. Tällöin ihminen varmasti pystyy Assemblerilla tekemään yhtä tehokkaan ohjelman kuin kääntäjä.
Se on tosiaan määrittelykysymys. Assembler on kuitenkin symbolista konekieltä ja on prosessori(tyyppi)kohtainen. Usein siinä kuitenkin pystyy määrittelemään nimiä, ja kohtia ohjelmassa/muistissa myös sybolisesti, eikä ohjelmoijan tarvitse perehtyä missä muistipaikassa ohjelman osa sijaitsee. Eikä ohjelmoijan todellakaan tarvitse kirjoittaa käskyjä heksoina tai binääreinä.
Minulta henk.koht. loppui innostus Assembleria kohtaan juuri, kuten mainitsitkin että C-kääntäjä optimoi paremmin kuin omat Assy-taidot riittää.
8th ei optimoi koodia häntärekursio tapausta lukuunottamatta ja pinopohjaisena se ei ole kauhean nopea tämmöisessä tehtävässä.
En viitsinyt edes ottaa aikaa, kun Raspberry PI 4B:llä ajettuna lämmöt melkein 90 asteessa ei varmasti hätyyttele kärkisijoja. Arviolta 6 - 7 minuuttia tuohon kuitenkin aikaa kului.
3.141592653 constant PI 0.000000001 constant epsilon 1 var, indeksi : jakaja=jakaja+2 swap 2 n:+ swap ; : laske-pi 1 \ jakaja 0 \ jakaja pii repeat dup PI epsilon n:~= if nip break else 4 2 pick n:/ n:+ \ jakaja pii=pii+4/jakaja jakaja=jakaja+2 \ jakaja=jakaja+2 pii 4 2 pick n:/ n:- \ jakaja pii=pii-4/jakaja jakaja=jakaja+2 \ jakaja=jakaja+2 pii 2 indeksi n:+! then again indeksi @ "Indeksi: %d\n" s:strfmt . "Laskettu PI: %f\n" s:strfmt . PI "PI vakio: %f\n" s:strfmt . ; : app:main 9 ## \ lasketaan 9 desimaalin tarkkuudella laske-pi ;
Indeksi: 629322341 Laskettu PI: 3.141592652 PI vakio: 3.141592653
Aihe on jo aika vanha, joten et voi enää vastata siihen.