Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: Mua kiehtoo pii!

Sivun loppuun

PetriKeckman [23.01.2022 16:22:48]

#

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.

peran [23.01.2022 18:57:26]

#

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

Grez [23.01.2022 19:08:00]

#

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 overhead

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

jalski [25.01.2022 17:48:12]

#

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

Grez [25.01.2022 18:37:58]

#

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

jalski [25.01.2022 18:45:21]

#

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

Grez [25.01.2022 20:41:30]

#

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.

jalski [26.01.2022 08:40:35]

#

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.

jalski [25.06.2022 09:35:36]

#

(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

PetriKeckman [25.06.2022 11:31:40]

#

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
03598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938

Process finished with exit code 0

jalski [25.06.2022 13:04:44]

#

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

PetriKeckman [25.06.2022 13:20:56]

#

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.

jalski [25.06.2022 13:32:32]

#

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.

PetriKeckman [25.06.2022 13:50:19]

#

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?

PetriKeckman [27.06.2022 19:04:06]

#

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

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

peran [28.06.2022 09:54:28]

#

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.

PetriKeckman [28.06.2022 15:42:35]

#

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.

PetriKeckman [28.06.2022 16:00:07]

#

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.

peran [28.06.2022 19:30:30]

#

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

jalski [28.06.2022 22:28:57]

#

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

Sivun alkuun

Vastaus

Muista lukea kirjoitusohjeet.
Tietoa sivustosta