Oppure

Loading
15/09/13 17:18
ape96
Ciao a tutti! :D

Ho un problema da risolvere utilizzando C++, e mi è tornato in mente questo forum!

Vado al punto, il problema è questo:

"Facendo cadere un grave da 100m di altezza sul pianeta Terra, esso impiega un determinato tempo a cadere se la g considerata è di 9.81 m/s^2. Realizzare un programma in C++ che calcoli la g ogni millimetro, e che quindi restituisca un tempo più accurato."

Infatti 9.81 è un'approssimazione.

I problemi che ho incontrato sono due, uno più strettamente sul linguaggio e uno più sulla fisica.

Non sono stato in grado di assegnare ad una variabile la massa della terra, infatti questa è troppo grande per essere scritta come numero normale! Ho utilizzato la variabile "long long", ma nemmeno in questo modo sono riuscito a fargliela leggere correttamente.
Ho mezzo una pezza in questo modo:

#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;
int main()
{
    long double M=5.9736;
    M=M*10000000000000000;
    long double r,h,G,g,t,i,c,ttot,rr,v;
    v=0;
    h=100;
    g=9.81;
    G=0.0000000000667;
    // M=5973600000000000000;
    r=6372797;
    ttot=0;
    t=sqrt((h/(g/2)));
    cout<<"Il grave si trova a 100 m di altezza.";
    cout<<" Se cade con una accelerazione costante di 9,81 m/s^2, impiega "<<t<<" secondi ad arrivare al suolo."<<endl;
    c=(h*1000)-1;
    r=6372797+h;
    t=sqrt((0.001+(v*t))/(g/2));
    v=v+(0.001/t);
   for (i=0; i<c; i++)
    {
        rr=(r*r)/100000000;
       g=G*(M/(rr));
    t=((v*-1)+sqrt((v*v)+(4*(g/2)*0.001))/g);
    v=v+(0.001/t);
    r=r-0.001;
     }
cout<<"Calcolando la g ogni millimetro percorso, il grave cade in "<<g<<" secondi."<<endl;
system("pause");
return 0;
}


Ho semplicemente "spostato" delle potenze di 10 dal numeratore (massa Terra) al denominatore (raggio Terra), ma vorrei capire se ci fosse un metodo migliore.

Infine, i due output dovrebbero essere veramente molto simili dato che anche ricalcolando la g non c'è tutta questa differenza, tuttavia mi vengono circa 2 decimi di secondo di differenza, che mi sembrano troppi: se qualcuno ha idee sono ben accette!

Mi rendo conto che quest'ultima parte è più un problema di fisica che di informatica, per cui anche solo capire quella questione degli 0 mi andrebbe bene ^^

Grazie mille!
aaa
15/09/13 23:14
pierotofy
Per questo genere di applicazioni dovresti usare una libreria come GMP (gmplib.org/).

Float e double sono approssimazioni dei numeri reali, e quando cominci ad aver bisogno di un certo livello di precisione (come nel caso di questo problema), e' normale avere dei problemi di arrotondamento.

Ad esempio, non c'e' modo di rappresentare in maniera precisa il valore 0.1 usando lo standard IEEE. docs.python.org/release/2.2.3/tut/…

Il mio blog: piero.dev
17/09/13 17:44
ape96
Ciao!

Ti ringrazio per la risposta, tuttavia non ho avuto bisogno di usare quella libreria: i calcoli eseguiti probabilmente non richiedevano una precisione così alta, dato che l'errore che facevo era un problema proprio del calcolo, non della approsimazione del compilatore!

Tuttavia il mio prof mi ha suggerito di scrivere i numeri usando la notazione "E", in questo modo ho potuto utilizzare tranquillamente la mia massa della Terra, la mia costante gravitazionale ecc.

Dopo essermi rimesso qua son riuscito finalmente a farlo! Ora è giusto. Posto il codice per chi ne avesse bisogno...

#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;
int main()
{
const float M=5.9736E24, G=6.67E-11;
float g,h,i,t,v,ttot,c,r;
r=6372797;
h=100;
g=9.81;
v=0;
ttot=0;
t=sqrt((h/(g/2)));
    cout<<"Il grave si trova a 100 m di altezza.";
    cout<<" Se cade con una accelerazione costante di 9,81 m/s^2, impiega "<<t<<" secondi ad arrivare al suolo."<<endl;
c=1000*h;
r=r+h;
t=sqrt((0.001+(v*t))/(g/2));
v=v+(g*t);
ttot=t;
    for (i=0; i<c; i++)
    {
       g=G*(M/(r*r));
       t=(-v+sqrt((v*v)+2*g*0.001))/g;
       v=v+(g*t);
       r=r-0.001;
       ttot=ttot+t;
   }
    cout<<"Calcolando la g ogni millimetro percorso, il grave cade in "<<ttot<<" secondi."<<endl;
system("pause");
return 0;
}
aaa