#include <cmath> #include <iostream> double asteetRadiaaneiksi(double); int main() { std::cout << sin(asteetRadiaaneiksi(180)) << std::endl; std::cin.get(); } double asteetRadiaaneiksi(double asteet) { double pii = 3.1415926535897932384626433832795; return (asteet / 180) * pii; }
Miksi tulos on 1.22465e-016? Windowsin laskimen mukaan 0.
Liukuluvuilla laskeminen ei ole tarkoilla arvoilla laskemista. Doublen tarkkuus on noin 15 merkitsevää numeroa. Vaikka oletkin kirjoittanut piin 32 numerolla, niin kääntäjä heittää käytännössä viimeisest 16-17 roskikseen kääntäessä.
Windowsin laskin saa luultavasti saman tuloksen, mutta pyöristää jonkun 14 desimaalin tarkkuudelle, jolloin tulokseksi tulee 0.
Tarvitsetko oikeasti tuloksen 16 desimaalin tarkkuudella?
Grez kirjoitti:
Tarvitsetko oikeasti tuloksen 16 desimaalin tarkkuudella?
Kolmen desimaalin tarkkuudella riittäisi (0.000).
No sittenhän riittää kun pyöristät saamasi tuloksen.
Tässä vielä esimerkki liukulukujen epätarkkuudesta:
#include <stdio.h> int main(void) { printf("%.30f\n", 0.1); }
$ ./a.out 0.100000000000000005551115123126
Jos nyt niuhotetaan niin eikö 0.1 ole tyyppiä double?
Nämä antaa vähän eri tulosteen (mutta silti epätarkkoja):
int main(void) { printf("%.30f\n", 0.1f); printf("%.30lf\n", 0.1); } 0.100000001490116120000000000000 0.100000000000000010000000000000
User137 kirjoitti:
Jos nyt niuhotetaan niin eikö 0.1 ole tyyppiä double?
printf("%.30f\n", 0.1f); printf("%.30lf\n", 0.1);
Nipotetaan lisaa. Printfin %f ottaa aina doublen. %lf ja %f ovat yksi ja sama; l ei tee tuossa mitaan. Printfille ei voi antaa floattia, vaan muunnos doubleksi tapahtuu aina ennen kutsua.
Aihe on jo aika vanha, joten et voi enää vastata siihen.