Verkeerde output

  • Onderwerp starter Onderwerp starter Bonk
  • Startdatum Startdatum
Status
Niet open voor verdere reacties.

Bonk

Gebruiker
Lid geworden
10 mei 2008
Berichten
5
Ik heb een programma geschreven en dit zou een file "abc.txt" moeten aanmaken en hierin de waarden van H, M_1 en M_2 moeten schrijven. Het programma schrijft deze waarden correct weg, maar voor M_1 en M_2 geeft hij telkens 0.1740 (wat overeenkomt met phi_1_min = 0 en phi_2_min =0-. Dit zou niet mogen, dus ik vermoed dat er een ergens een foutje in men programma zit. Ik denk dat phi_1_min en phi_2_min ergens nul wordt gesteld voor het wordt weggeschreven. Ik heb er al uren op zitten zoeken maar kan de fout niet vinden. Iemand een idee?

Alvast heel hard bedankt!

PS: De code van het programma:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "stdafx.h"
#include <ctype.h>

#define PI 4.0*atan(1.0);

void opslagen( double a , double b , double c);

int main(){

// Alle constanten en variabelen definiëren. Erachter staan telkens de eenheden waarin het uitgedrukt is.
// M_sat en de koppeling constanten hangen af van de temperatuur, ze zijn allemaal aangenomen bij O Kelvin.

double mu_0 = 0.000001256637062; // Wb/(A*m)
double H = -20.00; // T
double t1 = 0.0000000015; // m
double t2 = 0.0000000015; // m
double M_sat = 0.1740; // T (waarde voor Fe)
double phi_1 = 0; // radialen
double phi_2 = 0; // radialen
double phi_h = 0.2*PI; // radialen
double K = 0.5 * mu_0 * M_sat * M_sat; // J/m
double J_1 = 0.00005; // J/(m^2)
double J_2 = 0.000175; // J/(m^2)
double E ; // J
double E_min; // J
double phi_1_min = 0; // radialen
double phi_2_min = 0; // radialen
double M_1; // T
double M_2; // T

// Variabelen zonder fysische betekenis

double alpha = H;

// Waarden geven



while( H >= alpha && (-1)*alpha >= H){

E = mu_0*M_sat*H*(t1*cos(phi_1 - phi_h) + t2*cos(phi_2 - phi_h)) + K*t1*pow(cos(phi_1),2)*pow(sin(phi_1),2) + K*t2*pow(cos(phi_2) , 2)*pow(sin(phi_2) ,2) - J_1*cos(phi_1 - phi_2) - J_2*pow(cos(phi_1 - phi_2) ,2);
E_min = E;

while( phi_1 <= 6.28318530717958647692528676656 ){

while ( phi_2 <= 6.28318530717958647692528676656 ){
if(E < E_min){
E_min = E;
phi_1_min = phi_1;
phi_2_min = phi_2;
phi_2 = phi_2 + (3.14159265358979323846264338328/1800);
}
else{
phi_2 = phi_2 + (3.14159265358979323846264338328/1800);
}

}

phi_2 = 0;
phi_1 = phi_1 + (3.14159265358979323846264338328/1800);

}

// Nu heb je phi_1_min en phi_2_min voor H
// Nu moeten we de magnetisaties berekenen en vervolgens opslaan

M_1 = M_sat*cos(phi_1_min);
M_2 = M_sat*cos(phi_2_min);
opslagen( H , M_1 , M_2);

//Alle "tellers" resetten voor we aan de volgende H beginnen

phi_1 = 0;
phi_2 = 0;
H = H + 0.1;


}

}

void opslagen( double a , double b , double c){

// a is het magneetveld, b is M_1 en c is M_2
// declaraties

FILE *f;

// De file moet eerst geopend worden. Indien de file nog niet bestaat dan wordt die automatische aangemaakt.

f = fopen("abc.txt" , "a" );

// Wegschrijven van de gegevens

fprintf(f, "%f\t" , a);
fprintf(f, "%f\t" , b);
fprintf(f, "%f\n" , c);

// De file moet nog gesloten worden

fclose(f);


}
 
Ik weet niet precies wat je aan het doen bent dus ik kan het niet helemaal voor je uitzoeken. Maar een paar tips om je te helpen het probleem te vinden:

- Indentatie (ik weet niet of het aan de code tags van dit forum ligt maar ik zie het in ieder geval niet ^^)
Code:
int main(){
int bla;
bla = 0;
if ( bla == 0 ) {
}
}
naar
Code:
int main()
{
    int bla, bla2;
    bla = 0;
    if ( bla == 0 )
    {
        bla2 = 1;
    }
}

Dat houdt je code overzichtelijker.



- Geen magische nummers
Code:
                if(E < E_min)
                {
                    E_min = E;
                    phi_1_min = phi_1;
                    phi_2_min = phi_2;
                    phi_2 = phi_2 + (3.141592654/1800);
                } else {
                    phi_2 = phi_2 + (3.141592654/1800);
                }
naar
Code:
const double PI = 3.141592654;
....
                if(E < E_min)
                {
                    E_min = E;
                    phi_1_min = phi_1;
                    phi_2_min = phi_2;
                    phi_2 = phi_2 + (PI/1800);
                } else {
                    phi_2 = phi_2 + (PI/1800);
                }

Dat maakt je code een stuk leesbaarder.



- Zorg dat constanten ook echt constant zijn
Code:
    double mu_0 = 0.000001256637062; // Wb/(A*m)
naar
Code:
    const double mu_0 = 0.000001256637062; // Wb/(A*m)

Meestal geven we constanten ook met hoofdletters aan: MU_0 om het verschil tussen variabelen en constanten duidelijk te houden, maar dit hoeft niet per se ^^.



- Werk deze expressie uit tot een aantal kleinere expressies zodat het makkelijker te volgen is:
Code:
E = mu_0*M_sat*H*(t1*cos(phi_1 - phi_h) + t2*cos(phi_2 - phi_h)) + K*t1*pow(cos(phi_1),2)*pow(sin(phi_1),2) + K*t2*pow(cos(phi_2) , 2)*pow(sin(phi_2) ,2) - J_1*cos(phi_1 - phi_2) - J_2*pow(cos(phi_1 - phi_2) ,2);



Daarna kun je nagaan, met een debugger of bijvoorbeeld door printf() te gebruiken, of elke variabele wel de waarde heeft die hij moet hebben.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Andere kleine dingen die mij opvielen:

while( H >= alpha && (-1)*alpha >= H) mag ook while( H >= alpha && -alpha >= H) zijn ^^.

void opslagen( double a , double b , double c)... moet dat niet void opslaan( double a , double b , double c) zijn :P?
 
Laatst bewerkt:
Bedankt voor de tips.

Ik wou ze net toepassen, maar bots dan ineens op het volgende probleem:
Die 6,... is eigenlijk 2 keer Pi. Dus ik vervang in de while loop 6,.. door 2*PI. Als ik dit doe, dan geeft het echter een error. Hieronder staat het zoals ik het geschreven hebt, enig idee waar de fout zit?

while( phi_1 <= 2*PI ){

blabla

}

PS: Als foutmelding krijg ik dat er een haakje of een ; te weining is.
 
Hmmm ik denk dat je er een stukje voor misschien een haakje of iets bent vergeten.. Ik had al een begin gemaakt voor je waar 2*PI wel werkt:

Code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>

const double PI = 3.141592654;

void opslaan( double a , double b , double c );

int main() 
{
    // Alle constanten en variabelen definiëren. Erachter staan telkens de eenheden waarin het uitgedrukt is.
    // M_sat en de koppeling constanten hangen af van de temperatuur, ze zijn allemaal aangenomen bij O Kelvin.
    const double mu_0 = 0.000001256637062; // Wb/(A*m)
    double H = -20.00; // T
    double t1 = 0.0000000015; // m
    double t2 = 0.0000000015; // m
    double M_sat = 0.1740; // T (waarde voor Fe)
    double phi_1 = 0; // radialen
    double phi_2 = 0; // radialen
    double phi_h = 0.2 * PI; // radialen
    double K = 0.5 * mu_0 * M_sat * M_sat; // J/m
    double J_1 = 0.00005; // J/(m^2)
    double J_2 = 0.000175; // J/(m^2)
    double E ; // J
    double E_min; // J
    double phi_1_min = 0; // radialen
    double phi_2_min = 0; // radialen
    double M_1; // T
    double M_2; // T
    
    // Variabelen zonder fysische betekenis
    double alpha = H;
    
    // Waarden geven
    while( H >= alpha && -alpha >= H)
    {
        E = mu_0*M_sat*H*(t1*cos(phi_1 - phi_h) + t2*cos(phi_2 - phi_h)) + K*t1*pow(cos(phi_1),2)*pow(sin(phi_1),2) + K*t2*pow(cos(phi_2) , 2)*pow(sin(phi_2) ,2) - J_1*cos(phi_1 - phi_2) - J_2*pow(cos(phi_1 - phi_2) ,2);
        E_min = E;

        while( phi_1 <= 2*PI ) 
        {
            while ( phi_2 <= 2*PI )
            {
                if(E < E_min)
                {
                    E_min = E;
                    phi_1_min = phi_1;
                    phi_2_min = phi_2;
                    phi_2 = phi_2 + (PI/1800);
                } else {
                    phi_2 = phi_2 + (PI/1800);
                }
            }

            phi_2 = 0;
            phi_1 = phi_1 + (PI/1800);
        }

        // Nu heb je phi_1_min en phi_2_min voor H
        // Nu moeten we de magnetisaties berekenen en vervolgens opslaan
        M_1 = M_sat*cos(phi_1_min);
        M_2 = M_sat*cos(phi_2_min);
        opslaan( H , M_1 , M_2);

        //Alle "tellers" resetten voor we aan de volgende H beginnen
        phi_1 = 0;
        phi_2 = 0;
        H = H + 0.1;
    }
}

void opslaan( double a , double b , double c)
{
    // a is het magneetveld, b is M_1 en c is M_2
    // declaraties
    FILE *f;

    // De file moet eerst geopend worden. Indien de file nog niet bestaat dan wordt die automatische aangemaakt.
    f = fopen("abc.txt" , "a" );

    // Wegschrijven van de gegevens
    fprintf(f, "%f\t" , a);
    fprintf(f, "%f\t" , b);
    fprintf(f, "%f\n" , c);

    // De file moet nog gesloten worden
    fclose(f);
}
 
je moet iig bij je define je ; weghalen
ook is het slim om niet een berekening in je define te zetten maar gewoon de waarde (dan wordt je app sneller) dus:
#define PI 3.14159265358979323846

twee vraagjes nou:

E_min = E;
if( E < E_min )
i donno maar dat heeft niet veel zin, hij komt nu nooit binnen deze if


while ( phi_2 <= 2 * PI )
{
blabla
phi_2 = phi_2 + ( PI / 1800 );
}
phi_2 = 0;
wrm maak je hier geen for van?
 
E_min = E;
if( E < E_min )
i donno maar dat heeft niet veel zin, hij komt nu nooit binnen deze if

Heeeeeeeeeeeeel hard bedankt, ik denk dat dit het probleem is!
De eerste keer moet E = E_min, de andere keren moet E opnieuw berekend worden en vergeleken worden met E_min. Om die E opn ieuw te berekenen moet die dus binnen die while loops staan, wat niet het geval is. Ik ga meteen een simulatie laten lopen en eens even kijken wat het geeft, maar ik heb een sterk vermoeden dat het probleem nu opgelost is! :D
 
Ok, er zit nog een foutje in wat betreft eenheden, maar dat los ikzelf wel op.

Een tweede probleempje is dat 1 simulatie te veel tijd in beslag neemt. Ik zag hier al enkele tips om het programma sneller te maken, wel meer zo'n tips zijn altijd welkom :)
 
iig is aftellen sneller dan optellen maar in jouw geval is die winst minimaal

jij kunt het schrijven van de file beter maken, dus voor de gehele simulatie maar 1 keer openen en 1 keer sluiten
ook kun je misschien je preciesie aanpassen dus bij je loops niet
phi_1 += PI / 1800;
maar
phi_1 += PI / 180;
tenzij er een reden is waarvoor je hem deelt door zo'n groot getal (1800)
hetzelfde geld voor H += 0.1 maar dat zijn al redelijk grote stappen vergeleken bij die andere while loops

mocht je hem helemaal willen tweaken dan moet je niets gebruiken uit math.h
je kunt de pow's zelf doen en hashmaps maken van de goniometrische functies
 
iig is aftellen sneller dan optellen maar in jouw geval is die winst minimaal

jij kunt het schrijven van de file beter maken, dus voor de gehele simulatie maar 1 keer openen en 1 keer sluiten
ook kun je misschien je preciesie aanpassen dus bij je loops niet
phi_1 += PI / 1800;
maar
phi_1 += PI / 180;
tenzij er een reden is waarvoor je hem deelt door zo'n groot getal (1800)
hetzelfde geld voor H += 0.1 maar dat zijn al redelijk grote stappen vergeleken bij die andere while loops

mocht je hem helemaal willen tweaken dan moet je niets gebruiken uit math.h
je kunt de pow's zelf doen en hashmaps maken van de goniometrische functies

Die stappen kunnen niet groter, die moeten zo klein blijven.

Die functie pow, die kan ik inderdaad zelf schrijven, maar die cos en sin, daar heb ik geen flauw idee van. Ik heb zelfs nog nooit van hashmaps gehoord :o Ben dan ook nog maar een beginnertje :confused:
 
Vaak helpt het beter om een sneller algoritme te zoeken dan een hele hoop micro-optimalisaties te gaan doen ^^. Kijk of er een kortere manier is om te berekenen wat je wilt.

Maar functies zoals cos() en sin() zijn inderdaad niet erg snel. Als je een standaard aantal hoeken steeds invoert in die functies zou je misschien van tevoren 1 keer al die hoeken kunnen berekenen, in een array stoppen en dan in de rest van je programma uit die array halen.
Code:
// maak een array met de cosinus van 0 t/m 359 graden
const double graad = 2*PI / 360;
double cosinus[360];
for ( double i = 0; i < 360; ++i ) {
    graden[i] = cos(i * graad);
}

.....

double hoek = 24;
Fr = F1 * cosinus[hoek];
 
Laatst bewerkt:
als je dat zo gaat doen zou ik het echt met hashmaps doen en niet met arrays, de snelheidswinst van array naar hashmap is wel aanzienlijk

en wat arjan zegt klopt wel, de grootste winst valt te halen uit betere algoritmes, te beginnen met

Code:
E = mu_0 * M_sat * H * 
	( t1 * cos( phi_1 - phi_h ) + t2 * cos( phi_2 - phi_h ) ) + 
	K * t1 * pow( cos( phi_1 ), 2 ) * pow( sin( phi_1 ), 2 ) + 
	K * t2 * pow( cos( phi_2 ), 2 ) * pow( sin( phi_2 ), 2 ) - 
	J_1 * cos( phi_1 - phi_2 ) - 
	J_2 * pow( cos( phi_1 - phi_2 ), 2 );

probeer die te versimpelen. als je dat niet ziet zitten zoek dan naar het programma mathcad, misschien kan die je helpen

ps. ik weet dat het veranderen van die formule niets te maken heeft met het algoritme te veranderen maar je bent beginner dus dan krijg je wat moeite met maken van je eigen algoritme
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan