2012-12-12 35 views
5

Eventuali duplicati:
getting value of sine 180 as 1.22465e-16Sin e Cos funzioni che restituiscono risultati errati

sto calcolo di un punto sulla circonferenza del cerchio. Ho il raggio e il punto centrale del cerchio. Qui si potrebbe dire, grosso, c'è una formula diretta per lo stesso. Sì, angolo è in rad

x = x + r*sin(angle) 
y = y + r*cos(angle) 

Okay, ora il problema qui è anche se sto passando angolo in radianti. Eppure io non ottenere risposte corrette per l'angolo in basso menzionato

for 90 degree (rads = 1.5708) i get y axis = -4.3774e-08 
for 180 degree (rads = 3.14159) i get x axis = -8.74228e-08 
for 270 degree (rads = 4.71239) i get y axis = 1.19249e-08 
for 360 degree (rads = 6.28319) i get x asix = 1.74846e-07 

Io sono la conversione di Laurea in radianti con

return degrees * M_PI/180; 

non sono sicuro del perché questo sta accadendo. Deve esserci qualcosa di gravemente sbagliato.

Ecco il codice utilizzato per la conversione

float angle = DegreesToRadians(90); 

float x = sin(angle); 
float y = cos(angle); 

Qualcuno mi può aiutare con questo?

+1

codice postale per favore. – pdriegen

+1

Perché viene contrassegnato con "oggettivo-c"? –

risposta

8

M_PI è definita "math.h" come

#define M_PI  3.14159265358979323846264338327950288 

che è solo di circa la (irrazionale) numero Pi. Pertanto

cos(M_PI/2), sin(M_PI), cos(3*M_PI/2), sin(2*M_PI) 

sono solo circa zero. Pi non può essere rappresentato esattamente come float o double.

Dalla tua uscita presumo che tu abbia usato float. Poiché il numero di cifre significative di uno float è circa 7 e la pendenza (prima derivata) di sin() e cos() in corrispondenza di tali punti è +/- 1, direi che i risultati sono buoni come ci si può aspettare. Lavorare con double darebbe risultati migliori, ma non esattamente zero.

Quindi non c'è niente in modo errato sbagliato, non puoi aspettarti che il risultato di un calcolo in virgola mobile sia esatto.

+0

Allora, cosa suggerite voi ragazzi, non usando il float. Che tipo di dati utilizzo? Da quando, calcolando per 45 gradi, calcola perfettamente. Cosa si deve fare per ottenere i risultati esatti? – Kunjal

+0

@Kunjal: il risultato * è esatto * con precisione in virgola mobile. E non c'è alternativa al virgola mobile per le funzioni trigonometriche. - Se vuoi solo visualizzare alcuni punti, questo non è un problema, perché il risultato sarà comunque arrotondato ai pixel. - Altrimenti devi indicare più chiaramente cosa fai con i risultati e perché il risultato è un problema per te. –

+0

C'è un cerchio e ho bisogno di posizionare i pulsanti con un'angolazione diversa sulla circonferenza del cerchio. Quando uso la formula menzionata nella mia domanda originale, i risultati che ottengo dovranno essere manipolati. Se riesco a ottenere risultati esatti, è sempre meglio fare un CGPoint. Spero che le cose siano chiare. – Kunjal

0

In generale quando si ha a che fare con i float non è consigliabile confrontare i risultati (per uguali) con un numero specifico, che può essere 0, 1 o anche pi o e. -8.74228e-08 è abbastanza vicino per essere trattato come 0 in tutti i casi calcolabili. (In caso contrario, si ha un problema di significatività con float/double in ogni caso)

Nel caso in cui sia necessario confrontarli nel codice del programma, si dovrebbe piuttosto sottrarre i valori e confrontare il risultato con < o> e alcuni molto piccolo numero. per esempio.

if (sin(something*pi) < 0.0001f) ... 

piuttosto che

if (sin(something*pi) == 0) ... 
1

Per aggiungere un commento ad una domanda duplicate ...

Un'alternativa è quella di utilizzare i laureati o gradi anziché in radianti, in modo che i multipli di cerchi completi , così come i multipli di ogni quadrante sono interi e anche i seni e il coseno di gli argomenti possono essere rappresentati esattamente.

Inoltre si deve meravigliare quanto bene alcune implementazioni di librerie matematiche gestire multipli di pi: come la rappresentazione di pi greco in carri o raddoppia è fuori dal valore vero da qualche piccola quantità delta, allora ne consegue che N * (pi + -delta) è disattivato dal valore vero per N * delta. Di conseguenza in una libreria ben scritta sin ((pi/2) + (2 * pi) * n) aumenta con n; con la libreria scritta male, l'argomento viene valutato modulo approssimazione di 2 * pi, dando esattamente lo stesso offset per ogni n.

+0

La domanda che hai fatto riferimento è per java. Funzionerà lo stesso per Objective-c? Inoltre, non sono sicuro che Objective-C permetta di fare calcoli in gradi o gradi – Kunjal

+0

L'aritmetica in virgola mobile è più o meno indipendente dalla lingua - così come l'arte di dividere il cerchio con il numero intero di settori. Quest'ultimo è probabilmente utile solo in casi limitati e dove le funzioni trigonometriche sono eseguite con tabelle di ricerca. –

Problemi correlati