2009-06-10 13 views
31

Continuo a ricevere errori nella programmazione del mio iPhone quando provo a usare pi. Sto cercandopi nell'obiettivo C

float pNumber = 100*cos(2 * pi * (days/23)); 

ma ottengo gli errori che dicono:

_pi, fa riferimento a

_pi $ non_lazy_ptr

ho visto da qualche parte su internet per utilizzare M_PI e compila ma Non penso che mi dia il calcolo corretto.

quando provo:

float pNumber = 100*cos(2 * M_PI * (15746/23)); 

ottengo 0

Grazie

+0

In primo luogo, vorrei far galleggiare le mie costanti. – Nosredna

risposta

55
  • La divisione intera deve probabilmente essere costretti a un punto natante (lanciare uno dei numeri di un double - o usare la notazione 23.0 per indicare che si desidera una divisione in virgola mobile).
  • Provare a stampare M_PI e vedere cosa dice (printf("M_PI = %16.9g\n", M_PI); in C).
  • Hai inserito la dichiarazione per cos()? In caso contrario, potrebbe essere interpretato come una funzione che restituisce un numero intero (#include <math.h>).

codice Esempio (testato in C su Solaris 10 SPARC con GCC 4.3.3):

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

int main(void) 
{ 
    float pNumber = 100*cos(2 * M_PI * (15746/23)); 
    printf("M_PI = %16.9g\n", M_PI); 
    printf("pNum = %16.9g\n", pNumber); 
    pNumber = 100*cos(2 * M_PI * (15746/23.0)); 
    printf("pNum = %16.9g\n", pNumber); 
    return 0; 
} 

uscita Esempio:

M_PI =  3.14159265 
pNum =    100 
pNum =  -77.5711288 
+0

Come si esegue il cast di un int in un float nell'obiettivo C? – Xcoder

+2

Objective-C è un superset (C) perfetto di C, quindi puoi farlo allo stesso modo di C. – Nosredna

+0

Ho provato questo giorni = (float) giorni; float pNumber = 100 * cos (2 * pi * (giorni/23)); Ancora non funziona. Ottengo 0. Ecco cosa sto cercando di fare: http://stackoverflow.com/questions/975959/generate-a-periodic-value-based-on-dates – Xcoder

4

C/C++ e quindi Objective C/C++ non promuove gli interi in float quando si effettua una divisione normale.

Quindi in C/C++ l'espressione 15746/23 restituisce 567, non 567.71207 come si potrebbe ingenuamente aspettarsi.

C promuoverà gli interi a galleggianti, se necessario, se uno o l'altro operando è un galleggiante, per cui tutto quello che dovete fare è usare 15.746,0 o 23,0 nell'espressione, vale a dire il cambiamento di

float pNumber = 100*cos(2 * M_PI * (15746/23.0)); 

La 100 verrà automaticamente essere promosso perché cos restituisce un float (in realtà un double, ma ignorerò i problemi di flofe/double percisions). Il 2 viene promosso a float perché M_PI è un float. E il 15746 viene promosso a float perché 23.0 è un float.

Tuttavia, non sarebbe male aggiungere il 0,0 per tutte le costanti, cioè:

float pNumber = 100.0*cos(2.0 * M_PI * (15746.0/23.0)); 
+0

Grazie per l'ottimo suggerimento, Peter, comunque, sto ancora facendo qualcosa di sbagliato. Sto cercando di ottenere un numero compreso tra 0 e 100. Ecco l'offerta, 15746 è il numero di giorni da un compleanno. Ogni 23 giorni voglio un picco di 100. se dividi 12 dovresti ottenere "valle" che è uguale a 0. Quindi, voglio essere in grado di ottenere il numero di giorni di un dato giorno e vedere quale numero è tra 1 e zero in base a ogni 23 giorni.Questa formula è stata raccomandata come il modo per trovarlo da due persone, eppure ottengo il numero 15746. Qualche suggerimento? – Xcoder

+0

@Robb, che ne dici di mostrarci l'intero programma? Stiamo solo vedendo una linea qua e là. Dacci il programma più piccolo che fa quello che dici che fa. E dicci qual è il tuo compilatore C e quale sistema operativo stai utilizzando. – Nosredna

+0

Robb, cos restituisce un risultato con un intervallo compreso tra -1,0 e 1,0 e quindi si moltiplica per 100,0, pertanto il risultato deve avere un intervallo compreso tra -100,0 e 100,0. Quindi non vedo come si possa ottenere 15746. Infatti, quanto sopra genererà -77,571128. Dovrai pubblicare più codice, preferibilmente una funzione di esempio completa. –

1

Il problema è la divisione intera nella parte più interna dell'espressione, che tronca il valore (omettendo la parte frazionale). Un'opzione, come detto, è di rendere ogni costante un numero in virgola mobile, aggiungendo ".0" o "f" dopo di esso. In alternativa, puoi omettere le parentesi dall'espressione più interna interamente.Poiché M_PI è un numero in virgola mobile e la moltiplicazione in C è associativa a sinistra (ovvero procede da sinistra a destra) la prima moltiplicazione (2 * M_PI) verrà promossa a un valore float, così come ogni moltiplicazione successiva. Poiché cos() restituisce un valore float, a pNumber verrà assegnato un valore float senza aver eseguito alcuna divisione intera, quindi nessuna perdita di precisione. (Nota: in genere non è consigliabile contare sull'associatività o sulla precedenza dell'operatore, ma in questo caso sto solo cercando di dimostrare che funzionerebbe.)

Per quanto riguarda l'intervallo di numeri che dovresti aspettarti di vedere , ricorda che il coseno (non modificato) varia da -1 a +1, non da 0 a 1, quindi vedresti in realtà da -100 a 100 (in teoria). Per ottenere l'intervallo corretto, è necessario aggiungere 1, quindi moltiplicare per 50.

Per inciso, gli errori di compilazione che si verificano nel primo caso sono perché pi non è definito. La guida all'uso di M_PI è corretta: per le costanti matematiche, è sempre più intelligente (e più coerente) utilizzare ciò che fornisce il sistema. Se sei curioso, su Leopard queste costanti sono #definite in Math.h, linee 528-540. È possibile aprire il file utilizzando File> Apri rapidamente ... (Cmd-Shift-D) e digitando "Math.h" o facendo doppio clic su M_PI nel codice tenendo premuto Comando.

+0

quanta precisione è richiesta? ... qual è la costante M_PI definita come? .. cosa valuterebbe 355/113? –

0

Perché utilizzare una sinusoide in primo luogo?

Se l'obiettivo è quello di avere una funzione che va da 0 a 100 poi 100 a 0 a 23 giorni, è possibile utilizzare:

// x ranges from 0 to 2 
float x = (days % 23)/11.5; 
// pNumber is a saw ranging from 0 to 100 
float pNumber = 100 * abs(x - 1); 

È inoltre possibile sostituire la x con un coseno se si vuole veramente uno , come 2 * pi/23 ~ = 0.273, hai

float x = 1 + cos((days % 23)*0.273);