Un confronto Fortran – Python

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 😉

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Lascia un commento

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.