OK, ancora Fortran. Ma un attimo, domanda: dovendo decidere che linguaggio usare prossimamente quale conviene?
Nel caso specifico si tratta di una piccola struttura in cui recentemente si è usato esclusivamente il Visual Basic, a parte cose vecchie in Fortran IV e 77. I candidati possibili devono essere semplici, costare poco, possibilmente multipiattaforma (gli applicativi Fortran adesso sono su Ubuntu anche se, forse, chissà, si potrebbero portare su Windows) e usati frequentemente, niente newLISP.
Tra i candidati c’è, ovviamente, Python. Oggi facciamo un confronto su un caso finto ma verosimile.
Proviamo a calcolare i valori di seno e coseno nell’intervallo [0 .. 180] gradi, per ogni secondo d’arco. Usiamo le formule dello sviluppo in serie di Taylor, limitandoci ai primi termini, quelli che consentano di avere una discreta precisione e costringano il ‘puter a fare qualche calcolo.
Questa è la versione Python
#!/usr/bin/env python import math v = 2.0 f = ([1.0, 1.0, v]) for i in range(3, 14): v *= i f.append(v) def fsin(a): return a - pow(a, 3) / f[3] + pow(a, 5) / f[5] \ - pow(a, 7) / f[7] + pow(a, 9) / f[9] \ - pow(a, 11) / f[11] + pow(a, 13) / f[13] def fcos(a): return 1 - pow(a, 2) / f[2] + pow(a, 4) / f[4] \ - pow(a, 6) / f[6] + pow(a, 8) / f[8] \ - pow(a, 10) / f[10] + pow(a, 12) / f[12] pi = math.pi deg = 60 * 60 nsteps = 180 * deg step = pi / nsteps fmt = "{:3d} {:10.8f} {: 10.8f} {: 10.8f} {: 10.8e}" ssum = 0.0 csum = 0.0 for i in range (0, nsteps + 1): a = i * step s = fsin(a) ssum += s c = fcos(a) csum += c if (i % (10 * deg)) == 0: if c != 0.0: t = s / c print fmt.format(int(i / deg), a, s, c, t) print ssum, csum
Notare l’array f, cosa inusuale in Python, di solito si usano le liste.
Poi per il resto normale amministrazione.
E questa è la versione Fortran. Ormai sono abituato a usare il free format, dichiarare tutte le variabili e inoltre ho scoperto che l’uso dei moduli è comodo, anzi fondamentale.
program fconf !confronto con python use m_conf implicit none real(8) :: v, pi, step, ssum, csum real(8) :: a, s, c, t integer(4) :: deg, nsteps, i character(30) fmt_ f(1) = 1.0 do i = 2, 13 f(i) = i * f(i-1) end do pi = 4 * atan(1.0) deg = 60 * 60 nsteps = 180 * deg step = pi / nsteps fmt_ = "(i3, 3(1x, f11.8), 1x, e12.4)" ssum = 0.0 csum = 0.0 do i = 0, nsteps a = i * step s = fsin(a) ssum = ssum + s c = fcos(a) csum = csum + c if (mod(i,10 * deg) == 0) then if (c /= 0.0) t = s / c print fmt_, int(i / deg), a, s, c, t end if end do print *, ssum, csum end program
(Guardando le righe 27 e 29 si nota una cosa che ancora manca al Fortran: gli operatori del tipo +=
).
module m_conf <pre>implicit none real(8) :: f(13) contains function fsin(a) result(r) real(8) :: a, r r = a - a ** 3 / f(3) + a ** 5 / f(5) & & - a ** 7 / f(7) + a ** 9 / f(9) & & - a ** 11 / f(11) + a ** 13 / f(13) end function fsin function fcos(a) result(r) real(8) :: a, r r = 1 - a ** 2 / f(2) + a ** 4 / f(4) & & - a ** 6 / f(6) + a ** 8 / f(8) & & - a ** 10 / f(10) + a ** 12 / f(12) end function fcos end module
Piccola osservazione OT: Gedit si confonde quando visualizza file di Fortran, considera commento l’istruzione csum = 0.0
per via della C in prima colonna.
I risultati? L’output è visibile nelle immagini sopra, sostanzialmente coincidenti. I tempi di elaborazione sono interessanti, ecco la tabella di 5 run
Il Fortran è nettamente più veloce, per un fattore di 3.876 / 0.129 = 30. Però stiamo parlando di secondi. E allora questo non è più così importante e saranno da prendere in considerazione altre caratteristiche quali la semplicità e i gusti del programmatore. Anzi principalmente questi ultimi 😉
Poi ci sarebbero, volendo, altri linguaggi 😉
Trackback
[…] Questo post è la continuazione (OK, poi basta) di Un confronto Fortran – Python. […]
[…] questa dovrebbe essere l’ultima puntata del tormentone sviluppato negli ultimi post: comincio a detestarlo al pari del caldo afoso che […]