2015-03-05 21 views
5

Attualmente sto scrivendo un programma che deve prendere la parola radice quadrata. Dal momento che il valore che sto prendendo la radice quadrata di è positivo, l'ho appena lanciato su int. Quindi dire che per il seguente esempio:C++ - Come trasmettere correttamente il cast a int

int i = 16; 
int j = std::sqrt(i) 

j dovrebbe essere 4.

Mi chiedo, però, è possibile che sqrt restituisce 3,9999,999991 millions invece di 4,000,000001 millions o qualsiasi altra cosa, e il risultato di j è 3? Esistono regole che definiscono il comportamento in virgola mobile? Come posso convertirlo correttamente in un int?

+9

int intero = std :: round (floating_point); –

+0

Un po 'pertinente se ti interessa arrotondare: https://stackoverflow.com/questions/485525/round-for-float-in-c – tux3

+0

@ DieterLücking Penso che sarebbe rotondo a * più vicino *, mentre il risultato desiderato qui è quello arrotondare verso il basso da quale sarebbe la "vera" radice quadrata. Per esempio. sqrt (16) -> 4, sqrt (15) -> 3 –

risposta

3

Quasi tutto l'hardware ampiamente disponibile utilizza i numeri in virgola mobile IETF754, sebbene il C++ non lo richieda.

Supponendo numeri in virgola mobile IETF754 e una mappatura diretta delle ::std::sqrt al IETF754 galleggiante operazione radice quadrata punto, si ha la certezza di quanto segue:

  • 16 e 4 possono essere entrambi rappresentati esattamente in aritmetica in virgola mobile - infatti, numeri in virgola mobile a doppia precisione possono rappresentare qualsiasi numero intero a 32 bit esattamente
  • la radice quadrata restituisce il risultato che è più vicina ad essere esatto

Pertanto, tuo esempio will work fine.

In generale, il problema che hai accennato potrebbe accadere, ma per risolverlo devi fare una domanda più grande: in quali circostanze è un numero che è vicino all'integrale, davvero integrale?

Questo è in realtà più difficile di quanto possa sembrare, dal momento che si desidera calcolare il pavimento della radice quadrata, e quindi semplicemente l'arrotondamento non funzionerà per voi. Tuttavia, una volta che hai risposto a questa domanda per te stesso, l'implementazione di una soluzione dovrebbe essere piuttosto semplice. Ad esempio:

int i = 16; 
int j = std::sqrt(i); 
if((j + 1) * (j + 1) == i) j += 1; 
Problemi correlati