[FORTRAN-URGENTE] Consigli su dei programmi!

Ninphyl1
Salve ragazzi, volevo chiedervi dei consigli... Il mio professore di informatica mi ha dato delle tracce, io ho cercato di svolgerle, ma siccome mercoledì 9 c.m. dovrei andare a proporgli il mio lavoro, vorrei che mi deste un consiglio e mi aiutaste a vedere gli errori... Vi ringrazio in anticipo! Di seguito vi scrivo le tracce e quello che ho fatto io...

1) Letti due interi n e k, stampare il risultato della sommatoria k+ k^2 + k^3 + ... + k^n.

PROGRAM
INCIPIT NONE
INTEGER :: N,K,I,SUM

READ (*,*) N
READ (*,*) k
SUM = K

DO I=2,N
SUM = SUM + K^N
END DO

WRITE (*,*) SUM

STOP
END PROGRAM


2)Letto un vettore di interi, cancellare tutti gli elementi nulli. Esempio: a=(1,5,0,7,5,0,8) -> a=(1,5,7,5,8)

PROGRAM
IMPLICIT NONE
INTEGER, DIMENSION (100) :: A,B
INTEGER :: I,J,K,N

READ (*,*) N

DO I=1,N
J=1
READ (*,*) A(I)

IF (A(I).NE.0) THEN
B(J)=A(I)
J=J+1

ELSE
I=I+1

END IF
END DO

READ (*,*) K

DO J=1,K
WRITE (*,*) B(J)
END DO

STOP
END PROGRAM


3) Letta una matrice quadrata, restituire il numero di colonne della matrice aventi un numero di zeri minori di 5.
(su questo sono proprio dubbiosa)

PROGRAM
IMPLICIT NONE
INTEGER,DIMENSION(100,100) :: A
INTEGER :: I,J,N,SUM
BOOL :: PROP

SUM = 0
READ (*,*) N
PROP = TRUE
DO I=1,N
DO J=1,N
READ (*,*) A(I,J)
END DO
END DO

DO J=1,N
DO WHILE (PROP)
SUM = SUM + 1
END DO
END DO

END PROGRAM

(Per PROP intendo "nella colonna J ci sono meno di 5 zeri" )


4) Scrivere una funzione che verifichi, data una matrice quadrata d'ingresso, che la somma degli elementi su ogni riga sia costante.

INTEGER FUNCTION COSTANT (A,N,I,SUM,PROP)
IMPLICIT NONE
INTEGER, INTENT (IN) :: A, N, I, SUM
INTEGER INTENT (OUT) :: PROP

PROP = TRUE
I=1
DO WHILE ((PROP).AND.(I.LE.N-1))
PROP = (SUM(I) = SUM(I+1))
I = I+1
END DO

RETURN PROP

END FUNCTION

Vi ringrazio!

Risposte
Rggb1
A parte lo stile,

1) mi sembra corretto, anche se potresti evitare l'operazione di elevamento a potenza;

2) il primo ciclo non fa ciò che si richiede: assegni J a 1 all'interno del DO e inoltre incrementi I, che non va bene (verrebbe incrementato due volte...); quindi poni J a zero prima del ciclo e incrementalo dopo l'IF, togliendo l'ELSE e ovviamente togliendo anche l'incremento di I.
Inoltre, quando mostri a video il risultato, leggi un valore K per - presumo - mostrare i $k$ elementi del vettore B, ma non hai bisogno di farlo perché questo dato lo hai, è il valore di J; dunque utilizzalo come limite del ciclo e usa un altra variabile (I o K) come indice di ciclo [e ti accorgerai che forse hai una variabile che non ti serve ;)]
PS. ma "cancellare" gli elementi nulli significa copiare quelli non nulli su un altro array..?

3) poniamo il tuo 'PROP' sia definito in qualche modo, se usi un DO WHILE cicla indefinitamente, userei un normalissimo IF .. ENDIF

4) (PROP come sopra) a quanto mi ricordo io, il Fortran vorrebbe una sintassi tipo PROP=(SUM(I).EQ.SUM(I+1))

Ninphyl1
Ti ringrazio... Ma come posso evitare l'elevamento a potenza? Per quanto riguarda il secondo, penso che devo chiedere al professore se per lui va bene anche creare un nuovo array, ma nel caso lui dicesse di no, come posso cancellare gli zeri senza creare un nuovo array?
Nel caso andasse bene anche creare un nuovo array va bene così:

PROGRAM
IMPLICIT NONE
INTEGER, DIMENSION (100) :: A,B
INTEGER :: I,J,K,N

READ (*,*) N
J=0

DO I=1,N
READ (*,*) A(I)

IF (A(I).NE.0) THEN
B(J)=A(I)
END IF

J=J+1

END DO

DO K=1,J
WRITE (*,*) B(K)
END DO

STOP
END PROGRAM

Inoltre per l'ultimo, una volta corretto ".EQ.", il resto è corretto?

Ti ringrazio molto, mi sei di grande aiuto!

Rggb1
- Per evitare l'elevamento a potenza (ma considera è solo un "di più", funziona anche come l'hai scritto), puoi usare una variabile 'POW', che viene sempre moltiplicata per K e sommata a SUM, oppure sfruttare la proprietà
$sum_(i=1)^(k) k^i = k(1+k(1+k(...)))$

- Se devi usare un solo array, ci sono varie soluzioni, magari ne riparliamo.

- L'incremento di J va all'interno dell'IF, prima dell'assegnazione, di modo da avere:
"se l'elemento di A non è nullo, incrementa il numero di elementi non nulli e poni l'elemento nel vettore B"

- Per l'ultimo: direi di si, anche se manca del tutto il codice della SUM.

apatriarca
Se dovessi calcolare il valore di una serie geometrica in un'applicazione reale userei semplicemente
$\sum_{i=1}^{n} k^i = \frac{k - k^{n+1}}{1 - k}$
Ma immagino che per un esercizio del genere non si possa usare. In questo caso il metodo di Rggb è probabilmente migliore della somma delle potenze (è più robusta).

Siccome il numero di elementi non nulli fino ad un certo punto dell'array è inferiore o al massimo uguale al numero degli elementi, allora sovrascrivendo l'array originale non scriveresti sopra elementi non ancora considerati e quindi non ci sono problemi ad usare un solo array invece di due. Gli elementi non sovrascritti li puoi a questo punto semplicemente ignorare (considerando quindi una nuova dimensione per l'array).

Ninphyl1
Per quanto riguarda il primo e il primo è il terzo ho risolto.
Potresti spiegarmi la questione dell'univo array? Perchè nell'esempio non parla di due array ma di uno solo, non vorrei sbagliare...
E poi riguardo all'ultimo ti riscrivo il programma così magari mi dai l'ultima dritta:

INTEGER FUNCTION COSTANTE (A,N,I,J,SUM(I),PROP)
IMPLICIT NONE
INTEGER, INTENT (IN) :: A,N,I,J,SUM(I)
BOOL, INTENT (OUT) :: PROP

DO J=1,N
DO I=1,N
SUM(I)=A(I,J)+...+A(N,J)
END DO
END DO

I=1
PROP=TRUE

DO WHILE ((PROP).AND.(I.LE.N-1))
PROP=(SUM(I)).EQ.(SUM(I+1))
I=I+1
END DO

RETURN PROP
END FUNCTION

In teoria ho incluso nella funzione anche la somma dei termini della riga.
Che ne dici?

apatriarca
Stavo guardando il tuo secondo esercizio, ma perché non fai semplicemente una cosa come (nota che non conosco Fortran):

PROGRAM
IMPLICIT NONE
INTEGER, DIMENSION (100) :: A
INTEGER :: I, N

READ (*,*) N

DO I=1,N
READ (*,*) A(I)
END DO

DO I=1,N
IF (A(I).NE.0) THEN
WRITE (*,*) A(I)
END IF
END DO

STOP
END PROGRAM

Rggb1
"apatriarca":
Se dovessi calcolare il valore di una serie geometrica in un'applicazione reale userei semplicemente
$\sum_{i=1}^{n} k^i = \frac{k - k^{n+1}}{1 - k}$

... avevo detto "evitando l'esponente" ;)
E' una mia vecchia fissa, per non dover fare gli esponenti con gli INTEGER, ma spero di venir scusato: si deve considerare che ho imparato sul Fortran IV :-D
/ot>

@Ninphyl:
Cosa sarebbero quei puntini "..."? Un doppio ciclo va bene, ma per ogni riga metti SUM(I) a zero, e per ogni colonna ci sommi il valore dell'elemento in esame.

Per quanto riguarda l'uso del vettore singolo:
Soluzione (A): leggi un valore R, se non è nullo incrementi il numero elementi e lo memorizzi; funziona sicuramente, ma forse l'esercitazione prevede che
Soluzione (B): leggi tutti i valori del vettore come fai adesso, dopodiché usi un ciclo che, partendo dal primo elemento, 'sposta indietro' gli elementi se ne trova uno (o più) nulli.

Ho "descritto" l'algoritmo invece di proporre una soluzione già fatta; del resto mi sembra tu sia in grado di arrivarci, prova.

Rggb1
@apatriarca:

Ovvio, stessa soluzione... io ho proposto "non memorizzare se nullo", tu "non visualizzare se nullo". Identico risultato: KISS.

apatriarca
"Rggb":
[quote="apatriarca"]Se dovessi calcolare il valore di una serie geometrica in un'applicazione reale userei semplicemente
$\sum_{i=1}^{n} k^i = \frac{k - k^{n+1}}{1 - k}$

... avevo detto "evitando l'esponente" ;)
E' una mia vecchia fissa, per non dover fare gli esponenti con gli INTEGER, ma spero di venir scusato: si deve considerare che ho imparato sul Fortran IV :-D
/ot>[/quote]
Ma nel mio caso si devono fare solo due sottrazioni, una divisione e una potenza qualunque sia il valore di $n$. Anche se l'esponente è un'operazione abbastanza lenta, è comunque più veloce di calcolare tutta la somma per un valore sufficiente alto di $n$. Ma in ogni caso, normalmente quello che si vuole sapere è il valore al limite (supponendo che esista) e in questo caso si ottiene semplicemente $\frac{k}{1 - k}$ che non richiede il calcolo di esponenti.

Ninphyl1
GRAZIE MILLE!!!!!!!!!

Rggb1
"apatriarca":
Ma nel mio caso si devono fare solo due sottrazioni, una divisione e una potenza qualunque sia il valore di $n$. Anche se l'esponente è un'operazione abbastanza lenta, è comunque più veloce di calcolare tutta la somma per un valore sufficiente alto di $n$.

Sì, non era quello il punto, è chiaramente meglio in quel modo.

E' come ho accennato una "fissa" (solo mia, e anche un po' idiota, ça va sans dire...:-D) che risale a parecchi anni fa, a quando usavo il Fortran IV. Non sono così vecchio, ma a scuola quello c'era, quando lo standard de-facto era F77; e non c'era '^' ma solo '**' e per l'esponente era meglio usare la conversione da INTEGER a REAL (o DOUBLE PRECISION) e usare EXP(). Ovviamente ne è passata d'acqua sotto i ponti...
/ot>

Ninphyl1
Avevo dimenticato di proporvi un algoritmo.
TRACCIA: Scrivere una funzione che, dato un vettore di interi in ingresso, restituisca se il numero di numeri primi presenti nel vettore è maggiore di 5.
Siccome non riesco proprio ad impostarlo ho mandato un'e-mail al professore per chiedergli chiarimenti e lui mi ha fatto degli esempi:
1) v=(1,3,5,4,7,8,3,6)
se noi consideriamo solo i numeri primi abbiamo che 3,5,7,3 lo sono
mentre gli altri non lo sono. In questo caso la funzione restituisce
falso in quanto il numero di tali numeri primi è uguale a 4
2) v =(1,2,3,5,7,11,13,17)
in questo caso abbiamo che tutti tranne 1 sono numeri primi e quindi il numero di tali
numeri è superiore a 5 (ce ne sono infatti 7).

Ma nonostante ciò, pur avendo capito il "problema" non riesco ancora ad impostarlo, potreste aiutarmi, magari dandomi degli imput?


Ragazzi sono finalmente riuscita a fare almeno una bozza di questa funzione, vorrei che voi ci deste un'occhiata:

Intger Function 5_primi
implicit none
integer,intent(in),dimension(100)::v
integer,intent(in)::i,n,sum_primi
bool,intent(in)::primo
bool,intent(out)::prop

read(*,*)n
sum_primi=0
do i=1,n
read(*,*)v(i)

if (v(i).eq.primo)then
sum_primi=sum_primi+1
end if
end do
write(*,*)sum_primi
prop=true
if(sum_primi.gt.5)then
prop=true
else
prop=false
end if
write(*,*)prop

return prop
end function

ragazzi scusate se ci sono errori di battitura ma sono sull'iphone..
Fatemi sapere se ci sono errori! Grazie mille!!!


if

Maryel1
Ciao a tutti,
ho letto i vostri commenti e spero possiate aiutare anche me..purtroppo ne capisco davvero poco di fortran. Continuo a scrivere programmi ma il compilatore mi dice che trova degli errori cma non so quali possano essere. Avrei bisogno proprio di sapere l'ABC poichè ho davvero difficoltà a comprendere questo linguaggio. Questo dovrebbe essere un esercizio tipo d'esame (che ovviamente non mi funziona).Vi ringrazio per la disponibilità.

!c esame giugno2010
!c leggere e stampare una matrice di dimensioni (n,n).
!c copiare in un primo vettore gli elementi AL DI SOPRA della diagonale
!c principale ed in un secondo gli elementi AL DI SOTTO della stessa.
!c Calcolare il prodotto dei 2 vettori

Program matvet
Real A(20,20), v1(400), v2(400), v3(400)
integer i,n,j,k,r ,prod

!c carico la matrice. inizio e parte esecutiva.
write(*,*) "inserisci il numero di riche e colonne della matrice"
read (*,*) n

do 20 i=1,n
do 10 j= 1,n

write (*,*) "inserisci gli elementi(",i,")(",j,")della matrice"
read (*,*) A(i,j)

10 continue
20 continue

k=1
do 40 i=1, n-1
do 30 j= i+1, n
v1(k)=A(i,j)
k=k+1
30 continue
40 continue

k=1
do 60 i=1,n
do 50 j=1,n

if (i.GT.j) then
v2(k)= A(i,j)
k=k+1
endif

50 continue
60 continue

prod=0

do 70 i=1,k
prod= prod + v1(i)*v2(i)
70 continue

do 80 i=1,k
v3(i)=v1(i) * v2(i)
80 continue

do 90 i=1,k

write(*,*) "il vettore dei prodotti è :" v3(i)
90 continue

pause
end

Umby2
"Maryel":

Vi ringrazio per la disponibilità.




Ci sono diverse cose che non mi convincono.

- Nel primo ciclo giustamente, lavori con la colonna (i+1), nel secondo ciclo, invece scruti l'intera tabella e quindi sei costretto ad inserire "if (i.GT.j)". Non era meglio ragionare come hai fatto per il primo ciclo ?

- L'indice k lo sommi DOPO aver fatto il trasferimento nel vettore, pertanto risulta essere maggiorato di una unita, e considerato che lo usi successivamente per calcolare i prodotti, potrebbe darti fastidio (Vai a moltiplicare un qualcosa che non c'e').

- Il ciclo del prod ..... a che serve ? (istruzione 70)

Maryel1
Ciao,
e grazie per la risposta :D purtroppo io sono effettivamente alle primissime armi con fortran quindi mi baso su quel POCO che ho capito guardando altri esercizi e cerco di capirne la logica..allora per rispondere alle tue domande:

- non sapendo chiedere al programma di considerare solo la parte al di sotto della diagonale, ho considerato l'intera matrice (perchè così sapevo farlo)

- l'indice k lo uso per non far sovrapporre gli elementi nella stessa casella. Praticamente chiedo al programma (o almeno credo si faccia così) di partire dalla prima posizione nell'inserimento dei numeri e poi passare alle posizioni successive.


- Prod lo utilizzo per fare il prodotto..

apatriarca
Direi da partire da questo:
Continuo a scrivere programmi ma il compilatore mi dice che trova degli errori cma non so quali possano essere.

Quali sono gli errori che il compilatore ti trova? Che compilatore stai usando e con quali opzioni stai compilando il tuo programma?

A parte la mancanza di una virgola nella riga
write(*,*) "il vettore dei prodotti è :" v3(i)

sono riuscito a compilare il tuo programma. Questo è un esempio di esecuzione sul mio computer:
 inserisci il numero di riche e colonne della matrice
3
 inserisci gli elementi(           1 )(           1 )della matrice
1
 inserisci gli elementi(           1 )(           2 )della matrice
2
 inserisci gli elementi(           1 )(           3 )della matrice
3
 inserisci gli elementi(           2 )(           1 )della matrice
4
 inserisci gli elementi(           2 )(           2 )della matrice
5
 inserisci gli elementi(           2 )(           3 )della matrice
6
 inserisci gli elementi(           3 )(           1 )della matrice
7
 inserisci gli elementi(           3 )(           2 )della matrice
8
 inserisci gli elementi(           3 )(           3 )della matrice
9
 il vettore dei prodotti e' :   8.0000000
 il vettore dei prodotti e' :   21.000000
 il vettore dei prodotti e' :   48.000000
 il vettore dei prodotti e' :       +Infinity
PAUSE
To resume execution, type go.  Other input will terminate the job.

Per prima cosa leggi, ma non visualizzi la matrice che hai letto come richiesto dall'esercizio. Devi aggiungere un altro ciclo in cui visualizzi la matrice.

non sapendo chiedere al programma di considerare solo la parte al di sotto della diagonale, ho considerato l'intera matrice (perchè così sapevo farlo)

Non è difficile. Esattamente come nella parte superiore usi i $j > i$, nella parte inferiore devi usare $j < i$. $j$ dovrà quindi andare da $1$ a $j-1$. Dovresti essere in grado di scrivere il codice corrispondente (non è molto diverso da quello dei cicli precedenti).

Nota che $k$ è di un valore più alto del limite dell'array quando esci dai cicli per la parte inferiore. Gli indici degli array vanno infatti da 1 a k-1 (da 1 a 3 nell'esempio). Puoi notare infatti come l'ultimo valore visualizzato sia senza senso. Gli altri sono invece corretti.

Non mi è però del tutto chiaro che cosa il tuo professore intende con il prodotto dei 2 vettori. Non esiste infatti un ben definito prodotto tra vettori. Anche la tua implementazione non è del tutto chiara. Quello che stai facendo è:
prod $= v1 * v2$ (prodotto scalare)
$v3 = v1 * v2$ (prodotto componente per componente)
Perché li fai entrambi se visualizzi poi solo il secondo?

P.S. Ma è il tuo primo linguaggio di programmazione? Mi pare un po' ostico come primo approccio alla programmazione se questo fosse il caso..

Maryel1
Si questo è il mio primo ed unico approccio alla programmazione e non è più attivo il corso che ho seguito diversi anni fa (è su quelle info che sto lavorando).
Avrei la necessità di capire cio' che faccio poichè gli operatori e le strutture GROSSOMODO le conosco. Mi manca la capacità di sintetizzare la traccia e riprodurla tramite il fortran. Il programma che uso è force 2.0 ed in questo esempio particolare mi dà l'errore dove scrivo "do 10 j=1,n"
ho apportato qualche correzione di quelle che mi suggerivi. Grazie

!c esame giugno2010
!c leggere e stampare una matrice di dimensioni (n,n).
!c copiare in un primo vettore gli elementi AL DI SOPRA della diagonale
!c principale ed in un secondo gli elementi AL DI SOTTO della stessa.
!c Calcolare il prodotto dei 2 vettori

Program matvet
Real A(20,20), v1(400), v2(400), v3(400)
integer i,n,j,k

!c carico la matrice. inizio e parte esecutiva.
write(*,*) "inserisci il numero di righe e colonne della matrice"
read (*,*) n

do 20 i=1,n
do 10 j = 1,n

write (*,*) "inserisci gli elementi(",i,")(",j,")della matrice"
read (*,*) A(i,j)

10 continue
20 continue

k=1
do 40 i=1, n-1
do 30 j= i+1, n
v1(k)=A(i,j)
k=k+1
30 continue
40 continue

k=1
do 60 i=1,n
do 50 j=1,j-1

v2(k)=A(i,j)
k=k+1

50 continue
60 continue


do 80 i=1,k
v3(i)=v1(i) * v2(i)
80 continue

do 90 i=1,k

write(*,*) "il vettore dei prodotti Š :" ,v3(i)
90 continue

pause
end

Maryel1
il prodotto è scalare!!

apatriarca
Da quello che ho trovato su internet, force 2.0 sembra essere compatibile solo con fortran 77 mentre il tuo codice sembra essere in fortran 90 o successivo. Io l'ho compilato come tale almeno. Se fosse in fortran77 allora la formattazione è importante ed è inutile cercare di aiutarti se non usi il tag CODE per inserire il tuo codice correttamente formattato.

Maryel1
quello che non capisco è perchè altri programmi così scritti funzionano mentre ora inizia a darmi questi problemi..cmq ho scaricato un file che mi differenzia fortrann 77 da fortran 90 e mi dice le differenze..ho ricontrollato il tutto ed è corretto. Cmq l'esame me lo fara' fare su un foglio quindi seppure non dovresse girare con force ma fosse corretto con fortran 90 o successivi non credo ci sia alcun tipo di problema. Ti ricopio anche questo programma certamente più semplice che ugualmente non gira mi dà l'errore su STOP...com'è possibile?!Anche eliminando lo statement implicit none che è tipico del fortran90 il programma mi identifica sempre lo stesso errore. Potresti inoltre suggerirmi un approccio ai problemi..come ragionare in termini di programmazione..praticamente come dalla traccia impostare il procedimento nel modo più semplice. GRAZIE

Program grande
implicit none
integer v(10),x,i,j

write(*,*) "inserisci 10 numeri interi,uno per riga"
read(*,*)(v(i),i=1,10)

x=v(1)
j=1
do i=2,10

if (v(i).GT.x) then
x=v(i)
and j=i

end if
end do

write(*,*) "l'elemento",j,"è il più grande e vale=",x,

stop
end

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.