PDA

View Full Version : [C] Errore nel calcolo della radice quadrata?


MaxDembo81
07-12-2010, 20:46
Salve a tutti,
ho bisogno di calcolare in C la radice quadrata di un numero (2, 3 etc...) con la massima precisione possibile.
Ho scaricato DevC++ e usando questo programmino sciocco


#include<stdio.h>
#include<math.h>
#include<float.h>

main(){
double radice;
radice=sqrt(3);
printf("%1.20lf \n",radice);


system("pause");

}


ottengo 1.73 205 080 756 887 72.
Un po' poco mi dico.
Scopro che esistono i long double a precisione quadrupla ma devc++ non li supporta. Scarico lcc win32 e provo sia questi long double sia i qfloat, estensione del suddetto compilatore.

il programma usato è il seguente

#include<stdio.h>
#include<math.h>
#include<float.h>
#include<qfloat.h>

main(){
long double radice1;
qfloat radice2;
radice1=sqrt(3);
radice2=sqrt(3);
printf("%1.30Lf \n",radice1);
printf("%60.1qg \n",radice2);

system("pause");

}


e i risultati sono

radice1= 1.73 205 080 756 887 719 3 (tutto qua??)
radice2= 1.73 205 080 756 887 719 317 660 412 343 684 583 902 359 008 789 062 5

entrambi ben diversi da (fonte wiki)

1,73 205 080 756 887 729 352 744 634 150 587 236 694 280 525 381 038 ...

Allora ho installato Cgywin e tramite gcc ho compilato lo stesso programma mi restituisce

radice1= 1.73 205 080 756 887 719 318

ma come?
possibile che sbagli in questo modo? ma perchè?

tuccio`
07-12-2010, 21:17
se scrivi sqrt(3) non sei sicuro di richiamare la versione che prende un long double, dovresti scrivere sqrt((long double)3) per castare e essere sicuro di avere precisione "long double"

esempio con questo codice con visual c++:


#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
long double r1 = sqrt(3.0f);
long double r2 = sqrt((long double)3.0f);
printf("%1.30Lf\n%1.30Lf\n", r1, r2);
return 0;
}

output:

1.732050776481628400000000000000
1.732050807568877200000000000000

Gimli[2BV!2B]
07-12-2010, 21:55
Portando un passo oltre il consiglio di tuccio`, ho trovato riferimenti (http://bytes.com/topic/c/answers/212991-when-32-bit-double-precision-isnt-precise-enough) alla presenza di funzioni che svolgono i calcoli con precisione pari ai qfloat che stai utilizzando, il cui nome è quello standard con suffisso q.
Per esempio puoi provare:#include <stdio.h>
#include <qfloat.h>

int main()
{
qfloat q = 2;
qfloat r = sqrtq(q);
printf("%80.70qf\n",r);
}(io non ho modo di testare, quindi ti propongo la cosa con beneficio di inventario)

bender86
08-12-2010, 11:13
Se vuoi la massima precisione possibile devi usare delle librerie come Apfloat (http://www.apfloat.org/apfloat/) o GSL (http://www.gnu.org/software/gsl/). Per esempio:

#include <apfloat.h>
#include <sstream>
#include <iostream>

int main()
{
apfloat a("3", 1000); // preciso fino alla millesima cifra.
apfloat b = sqrt(a);
std::stringstream stream;
stream << b;
std::cout << stream.str() << std::endl;
return 0;
}
risultato:
1,7320508075688772935274463415058723669428052538103806280558069794519330
169088000370811461867572485756756261414154067030299699450949989524788116
555120943736485280932319023055820679748201010846749232650153123432669033
228866506722546689218379712270471316603678615880190499865373798593894676
503475065760507566183481296061009476021871903250831458295239598329977898
245082887144638329173472241639845878553976679580638183536661108431737808
943783161020883055249016700235207111442886959909563657970871684980728994
932964842830207864086039887386975375823173178313959929830078387028770539
133695633121037072640192491067682311992883756411414220167427521023729942
708310598984594759876642888977961478379583902288548529035760338528080643
819723446610596897228728652641538226646984200211954841552784411812865345
070351916500166892944154808460712771439997629268346295774383618951101271
486387469765459824517885509753790138806649619119622229571105552429237231
92197738262561631468842032853716682938649611917049738836395495938

Supdario
08-12-2010, 11:56
Salve a tutti,
ho bisogno di calcolare in C la radice quadrata di un numero (2, 3 etc...) con la massima precisione possibile.
Ho scaricato DevC++ e usando questo programmino sciocco


#include<stdio.h>
#include<math.h>
#include<float.h>

main(){
double radice;
radice=sqrt(3);
printf("%1.20lf \n",radice);


system("pause");

}


ottengo 1.73 205 080 756 887 72.
Un po' poco mi dico.
Scopro che esistono i long double a precisione quadrupla ma devc++ non li supporta. Scarico lcc win32 e provo sia questi long double sia i qfloat, estensione del suddetto compilatore.

il programma usato è il seguente

#include<stdio.h>
#include<math.h>
#include<float.h>
#include<qfloat.h>

main(){
long double radice1;
qfloat radice2;
radice1=sqrt(3);
radice2=sqrt(3);
printf("%1.30Lf \n",radice1);
printf("%60.1qg \n",radice2);

system("pause");

}


e i risultati sono

radice1= 1.73 205 080 756 887 719 3 (tutto qua??)
radice2= 1.73 205 080 756 887 719 317 660 412 343 684 583 902 359 008 789 062 5

entrambi ben diversi da (fonte wiki)

1,73 205 080 756 887 729 352 744 634 150 587 236 694 280 525 381 038 ...

Allora ho installato Cgywin e tramite gcc ho compilato lo stesso programma mi restituisce

radice1= 1.73 205 080 756 887 719 318

ma come?
possibile che sbagli in questo modo? ma perchè?

La funzione per calcolare la radice quadrata con i long double non è sqrt, ma sqrtl.
Assicurati inoltre di non avere attivato le ottimizzazioni del compilatore, che spesso aumentano le prestazioni a scapito della precisione delle operazioni in floating point.