View Full Version : [python to C] "Traduzione" codice in C
Salve, ho trovato in rete un codice (non lungo) che vorrei "tradurre" in codice C.
Python lo conosco..ma non cosi tanto:P
Non saprei come tradurre questo:
def makeMatrix(I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill]*J)
return m
Che in pratica ti restituisce I matrici di grandezza J.
Es: se I=3, J=4: [[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
Non l'ho testata e l'ho scritta in 5 min ma dovrebbe essere giusta (a meno di errori di sintassi :p )
Il typedef può essere utile per cambiare il tipo di dati che deve contenere la matrice senza dover fare un find/replace, di solito li metto quando faccio funzioni generiche di questo tipo!
typedef double datum
void makeMatrix(datum **nMatrix, unsigned int i, unsigned int j, datum fill) {
unsigned int k, l;
nMatrix = (datum **) malloc(sizeof(datum *) * j);
for(k = 0; k < j; k++) {
nMatrix[k] = (datum *) malloc(sizeof(datum) * i);
for(l = 0; l < i; l++) {
nMatrix[k][l] = fill;
}
}
}
cdimauro
09-06-2009, 11:48
Salve, ho trovato in rete un codice (non lungo) che vorrei "tradurre" in codice C.
Python lo conosco..ma non cosi tanto:P
Non saprei come tradurre questo:
def makeMatrix(I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill]*J)
return m
Che in pratica ti restituisce I matrici di grandezza J.
Es: se I=3, J=4: [[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
Visto che t'hanno già dato la soluzione, ti riscrivo quella in Python che hai riportato:
def makeMatrix(I, J, fill=0.0):
return [[fill] * J for i in xrange(I)]
che è pure più efficiente. :cool:
!k-0t1c!
09-06-2009, 12:42
Bisogna considerare che in C comunque bisogna allocare memoria nello heap esplicitamente quindi è anche possibile ritornare un risultato esplicitamente, ma dopo l'uso del risultato bisognerà chiamare free sul puntatore ritornato dalla funzione. Questo rende necessario l'uso di pattern quali quello suggerito nella soluzione dove è necessario passare un puntatore alla memoria in cui scrivere il risultato.
Non l'ho testata e l'ho scritta in 5 min ma dovrebbe essere giusta (a meno di errori di sintassi :p )
Il typedef può essere utile per cambiare il tipo di dati che deve contenere la matrice senza dover fare un find/replace, di solito li metto quando faccio funzioni generiche di questo tipo!
typedef double datum
void makeMatrix(datum **nMatrix, unsigned int i, unsigned int j, datum fill) {
unsigned int k, l;
nMatrix = (datum **) malloc(sizeof(datum *) * j);
for(k = 0; k < j; k++) {
nMatrix[k] = (datum *) malloc(sizeof(datum) * i);
for(l = 0; l < i; l++) {
nMatrix[k][l] = fill;
}
}
}
Grazie per la pronta risp!! non ho ben capito "typedef double datum", perché poi per utilizzare questa funzione, il parametro datum cos'é?
grazie
!k-0t1c!
09-06-2009, 13:06
datum diventa semplicemente un alias per double, in questo caso. In caso dovessi tu un giorno decidere che vuoi operare su una matrice di interi, tuttavia, ti basterebbe cambiare il double del typedef con int. E così via...
scusate la mia ignoranza..ma i due * che significano? (super puntatore?:)
grazie
scusate la mia ignoranza..ma i due * che significano? (super puntatore?:)
grazie
puntatore a puntatore :O
!k-0t1c!
09-06-2009, 14:02
Puntatore ad un puntatore. Usato per una matrice bidimensionale visto che ogni dimensione dell'array implica l'aggiunta di un livello di indirection.
scusate la mia ignoranza..ma i due * che significano? (super puntatore?:)
grazie
come ti hanno già detto i due * indicano puntatori a puntatori. Si può fare anche utilizzando un unico puntatore ma questo ne peggiorerebbe un pochino la leggibilità (secondo me non molto, cmq così è più chiaro)
avrei un'altra domanda da porvi..in python definisco la class NN, ma poi ho questo:
def __init__(self, ni, nh, no):
# number of input, hidden, and output nodes
self.ni = ni + 1 # +1 for bias node
self.nh = nh
self.no = no
# activations for nodes
self.ai = [1.0]*self.ni
self.ah = [1.0]*self.nh
self.ao = [1.0]*self.no
# create weights
self.wi = makeMatrix(self.ni, self.nh)
self.wo = makeMatrix(self.nh, self.no)
__init__ é una funzione, ma in C che uso? O penso che in questo caso sia meglio parlare di C++, o sbaglio?
grazie
cdimauro
10-06-2009, 10:58
Non sbagli: __init__ è il "costruttore" di una classe in Python. ;)
Non sbagli: __init__ è il "costruttore" di una classe in Python. ;)
ma quindi tradotto in C?
semplicemente tolgo il def __init__?
class NN
{
self.ni = ni + 1;
self.nh = nh;
self.no = no;
# activations for nodes
self.ai = [1.0]*self.ni;
self.ah = [1.0]*self.nh;
self.ao = [1.0]*self.no;
# create weights
self.wi = makeMatrix(self.ni, self.nh);
self.wo = makeMatrix(self.nh, self.no);
e poi dentro scrivo delle funzioni? o chiudo class, e scrivo le funzioni?
banryu79
10-06-2009, 11:05
Non vorrei dire cazzate, ma potresti tardurre la classe Python con una struct... a quel punto il costruttore (__init__) diventa una normale funzione di inizializzazione della struct.
||ElChE||88
10-06-2009, 11:05
ma quindi tradotto in C?
Il C non è un linguaggio ad oggetti, quindi il concetto di classi non esiste. Al massimo puoi usare uno struct per memorizzare le variabili e passarlo alle funzioni che vuoi implementare.
appunto..per c++ che dovrei fare?
banryu79
10-06-2009, 11:21
appunto..per c++ che dovrei fare?
Ma non si parlava di C, scusa?
Comunque in C++ le classi ci sono eccome, ed è possibile programmare secondo la prospettiva orientata agli oggetti.
Quindi puoi tradurre la tua classe Python con una classe C++...
Il metodo __init__ di Python diverrà un costruttore nella versione C++ (in cui ti dedi anche preoccupare del distruttore, però).
Certo che per fare una traduzione da un linguaggio a un'altro (tra l'altro da un linguaggio che ha un dynamic type system a uno che si basa su uno static type system, tanto per citare una differenza) senza troppi problemi e troppe perdite di tempo credo ci voglia una fondata conoscenza e esperienza in entrambi...
Se poi ti devi fiondare su C++, ti ci vuole un santo protettore (prova ad accendere un cero a 'san Cionci', oppure a 'Tommo il martire', :) sono i beati che ti possono venire maggiormente in aiuto, secondo me)
dici che é cosi difficile? perché il codice completo non é cosi complicato:
import math
import random
import string
random.seed(0)
# calculate a random number where: a <= rand < b
def rand(a, b):
return (b-a)*random.random() + a
# Make a matrix (we could use NumPy to speed this up)
def makeMatrix(I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill]*J)
return m
# our sigmoid function, tanh is a little nicer than the standard 1/(1+e^-x)
def sigmoid(x):
return math.tanh(x)
# derivative of our sigmoid function, in terms of the output (i.e. y)
def dsigmoid(y):
return 1.0 - y**2
class NN:
def __init__(self, ni, nh, no):
# number of input, hidden, and output nodes
self.ni = ni + 1 # +1 for bias node
self.nh = nh
self.no = no
# activations for nodes
self.ai = [1.0]*self.ni
self.ah = [1.0]*self.nh
self.ao = [1.0]*self.no
# create weights
self.wi = makeMatrix(self.ni, self.nh)
self.wo = makeMatrix(self.nh, self.no)
# set them to random vaules
for i in range(self.ni):
for j in range(self.nh):
self.wi[i][j] = rand(-0.2, 0.2)
for j in range(self.nh):
for k in range(self.no):
self.wo[j][k] = rand(-2.0, 2.0)
# last change in weights for momentum
self.ci = makeMatrix(self.ni, self.nh)
self.co = makeMatrix(self.nh, self.no)
def update(self, inputs):
if len(inputs) != self.ni-1:
raise ValueError, 'wrong number of inputs'
# input activations
for i in range(self.ni-1):
#self.ai[i] = sigmoid(inputs[i])
self.ai[i] = inputs[i]
# hidden activations
for j in range(self.nh):
sum = 0.0
for i in range(self.ni):
sum = sum + self.ai[i] * self.wi[i][j]
self.ah[j] = sigmoid(sum)
# output activations
for k in range(self.no):
sum = 0.0
for j in range(self.nh):
sum = sum + self.ah[j] * self.wo[j][k]
self.ao[k] = sigmoid(sum)
return self.ao[:]
def backPropagate(self, targets, N, M):
if len(targets) != self.no:
raise ValueError, 'wrong number of target values'
# calculate error terms for output
output_deltas = [0.0] * self.no
for k in range(self.no):
error = targets[k]-self.ao[k]
output_deltas[k] = dsigmoid(self.ao[k]) * error
# calculate error terms for hidden
hidden_deltas = [0.0] * self.nh
for j in range(self.nh):
error = 0.0
for k in range(self.no):
error = error + output_deltas[k]*self.wo[j][k]
hidden_deltas[j] = dsigmoid(self.ah[j]) * error
# update output weights
for j in range(self.nh):
for k in range(self.no):
change = output_deltas[k]*self.ah[j]
self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k]
self.co[j][k] = change
#print N*change, M*self.co[j][k]
# update input weights
for i in range(self.ni):
for j in range(self.nh):
change = hidden_deltas[j]*self.ai[i]
self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j]
self.ci[i][j] = change
# calculate error
error = 0.0
for k in range(len(targets)):
error = error + 0.5*(targets[k]-self.ao[k])**2
return error
def test(self, patterns):
for p in patterns:
print p[0], '->', self.update(p[0])
def weights(self):
print 'Input weights:'
for i in range(self.ni):
print self.wi[i]
print
print 'Output weights:'
for j in range(self.nh):
print self.wo[j]
def train(self, patterns, iterations=1000, N=0.79, M=0.1):
# N: learning rate
# M: momentum factor
for i in xrange(iterations):
error = 0.0
for p in patterns:
inputs = p[0]
targets = p[1]
self.update(inputs)
error = error + self.backPropagate(targets, N, M)
if i % 100 == 0:
print 'error %-14f' % error
def demo():
# Teach network XOR function
pat = [
[[0,1,1,1,0,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1], [1]] ]
pat2 = [
[[1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1,
1,1,1,1,1,
1,0,0,0,1,
1,0,0,0,1]],
]
# create a network with two input, two hidden, and one output nodes
n = NN(35, 3, 1)
# train it with some patterns
n.train(pat)
# test it
n.test(pat2)
if __name__ == '__main__':
demo()
non mi sembra impossibile..pero le classi non le conosco, per quello ho chiesto aiuto in quel punto
banryu79
10-06-2009, 12:13
dici che é cosi difficile?
non mi sembra impossibile..pero le classi non le conosco, per quello ho chiesto aiuto in quel punto
Bhe aspetta, io pensavo tu dovessi fare una specie di porting ben più consistente di una sola classe Python :D .
Certo ce la puoi fare, ma se non sai niente di C++ la vedo dura, a meno che qualche anima pia non prenda tutta la classe Python che hai postato e ti posti per filo e per segno un equivalente codice C++ della stessa.
O più anime pie lo facciano ognuna un pezzetto, a rate.
L'alternativa è che tu speda qualche giorno (una settimana) a familiarizzarti con il linguaggio C++, in generale, e in particolare con il costrutto class e i concetti che ci ruotano attorno.
Sarebbe bene anche studiare come funzionano le variabili, e i puntatori (facciamo un due settimane, via; presuppongo che tu non sappia niente di C/C++ e di puntatori).
Poi provi a realizzare una implementazione di quella classe in C++, e per gli errori/problemi specifici procedi chiedendo aiuto al forum.
Se qualcuno mi contraddice dimostrando che ho sparato fanfarate e ti aiuta concretamente sarò solo che felice per te :)
ma io qualcosa di C ne so (dire che lo palleggio é un'eresia se confrontato con la vostra sapienza in materia..pero so il fatto mio).
cdimauro
10-06-2009, 13:20
Sei fortunato che hanno usato Python come un qualunque linguaggio con programmazione strutturata e (ben poco) a oggetti. :stordita:
Se avessi beccato un mio sorgente avresti perso meno tempo a capire come funziona e riscrivertelo da zero. :D
quindi come potrei fare?
grazie
io ci avrei provato ma non conosco python.. e non me ne voglia cdimauro ma senza conoscerlo mi sembra ben poco intuibile..
~FullSyst3m~
11-06-2009, 12:15
io ci avrei provato ma non conosco python.. e non me ne voglia cdimauro ma senza conoscerlo mi sembra ben poco intuibile..
Non conosci Python??? :eek: Eresia!!!!!!
Studialo prima che cdimauro ti crocifigga :D
cdimauro
14-06-2009, 20:23
quindi come potrei fare?
grazie
Non vedo quale sia il problema.
Conosci (bene) il C++? Se sì, e se conosci un briciolo di Python, la traduzione è abbastanza lineare.
Non vedo quale sia il problema.
Conosci (bene) il C++? Se sì, e se conosci un briciolo di Python, la traduzione è abbastanza lineare.
conosco il C++ dal C..quindi non lo conosco bene, se no non avrei chiesto aiuto:P
cdimauro
15-06-2009, 07:21
Allora mi sa che più che un aiuto ti servirebbe qualcuno che ti traduca il programma. ;)
banryu79
15-06-2009, 16:21
mi autoquoto:
L'alternativa è che tu speda qualche giorno (una settimana) a familiarizzarti con il linguaggio C++, in generale, e in particolare con il costrutto class e i concetti che ci ruotano attorno.
Sarebbe bene anche studiare come funzionano le variabili, e i puntatori (facciamo un due settimane, via; presuppongo che tu non sappia niente di C/C++ e di puntatori).
Poi provi a realizzare una implementazione di quella classe in C++, e per gli errori/problemi specifici procedi chiedendo aiuto al forum.
Ce le hai queste "due settimane" (stima tirata molto a occhio) da investire nello studio? (Diciamo 2-3 orette al giorno/notte, a scelta/possibilità).
Perchè oramai avrai visto anche da solo che non ce la fai andando "a spanne" con le attuali conoscenze che possiedi.
Va da se: o incrementi le tue conoscenze specifiche, oppure te le procuri tramite terzi che ti fanno il lavoro.
eh mi sa che mi mettero a studiare:P
ma a studiare solo le classi in C++,giusto?
cdimauro
16-06-2009, 07:11
Dovrebbe essere sufficiente.
Wing_Zero
16-06-2009, 17:30
ma io qualcosa di C ne so (dire che lo palleggio é un'eresia se confrontato con la vostra sapienza in materia..pero so il fatto mio).
Sai il fatto tuo ...e pensi che **pippo sia un superpuntatore?
In pratica non hai mai visto un doppio puntatore...:doh:
Ritengo che il fatto tuo sia ben poca cosa...
é come se ti cucino una pasta aglio olio peperoncino..mi dici che un po' di piccante ti piace, e poi stai attaccato al lavandino con la lingua che penzola...un po' relativa la cosa (il livello di "piccantezza"..come di conoscenza...), pero non mi ritengo assolutamente ignorante in materia (visto le domande che girano su sto forum:D)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.