2009-06-10 15 views
31

Recibo un error en la programación de mi iPhone cuando intento usar pi. Estoy intentandopi en el objetivo C

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

pero me da errores diciendo:

_pi, referenciados a partir

_pi $ non_lazy_ptr

que vi en algún lugar de Internet para utilizar M_PI y se compila pero No creo que me dé el cálculo correcto.

cuando intento:

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

llego 0

Gracias

+0

Primero, haré que mis constantes floten. – Nosredna

Respuesta

55
  • La división entera, probablemente necesita ser forzada a tener un punto uno (fundido uno de los números a una variable doble - o use la notación 23.0 para indicar que quiere una división de punto flotante).
  • Intente imprimir M_PI y vea lo que dice (printf("M_PI = %16.9g\n", M_PI); en C).
  • ¿Incluyó la declaración para cos()? De lo contrario, puede interpretarse como una función que devuelve un número entero (#include <math.h>, quizás).

Ejemplo código (probado en C en 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; 
} 

salida Ejemplo:

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

¿Cómo se convierte un int en un flotante en el objetivo C? – Xcoder

+2

Objective-C es un superconjunto perfecto (creo) de C, por lo que puede hacerlo de la misma manera que en C. – Nosredna

+0

He intentado esto days = (float) days; flotante pNumber = 100 * cos (2 * pi * (días/23)); Todavía no funciona. Tengo 0. Esto es lo que estoy tratando de hacer: http://stackoverflow.com/questions/975959/generate-a-periodic-value-based-on-dates – Xcoder

4

C/C++ y por lo tanto Objetivo C/C++ no promueve que los enteros floten cuando se hace una división normal.

Así que en C/C++ la expresión 15746/23 se evalúa a 567, no a 567.71207 como es de esperar ingenuamente.

C promoverá enteros a flote cuando sea necesario si uno u otro operando es un flotador, todo lo que tiene que hacer es usar 15.746,0 o 23.0 en su expresión, es decir, el cambio a

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

El 100 automáticamente ser promovido porque cos devuelve un flotador (en realidad un doble, pero voy a ignorar problemas de flotante/doble percusión). El 2 se promueve a un float porque M_PI es un float. Y el 15746 se promueve a una flotación porque 23.0 es un flotador.

Sin embargo, no estaría de añadir el 0,0 a todas las constantes, es decir:

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

Gracias por la gran sugerencia Peter sin embargo, todavía estoy haciendo algo mal. Estoy tratando de obtener un número entre 0 y 100. Aquí está el trato, 15746 es el número de días desde un cumpleaños. Cada 23 días quiero un máximo de 100. Si divides 12, debes obtener "valle" que es igual a 0. Entonces, quiero poder obtener el número de días de un día determinado y ver qué número hay entre ellos. 1 y cero en base a cada 23 días.Esta fórmula fue recomendada como la forma de encontrarla por dos personas, sin embargo, estoy obteniendo el número 15746. ¿Alguna sugerencia? – Xcoder

+0

@Robb, ¿qué tal si nos muestras todo el programa? Estamos viendo una línea aquí y allá. Danos el programa más pequeño que hace lo que dices que hace. Cuéntenos cuál es su compilador de C y qué sistema operativo está ejecutando. – Nosredna

+0

Robb, cos devuelve un resultado con un rango de -1.0 a 1.0, y luego se multiplica por 100.0, por lo que el resultado debe tener un rango de -100.0 a 100.0. Así que no puedo ver cómo puede obtener 15746. De hecho, lo anterior generará -77.571128. Deberá publicar más código, preferiblemente una función de ejemplo completa. –

1

El problema es la división de enteros en la parte más interna de la expresión, que trunca el valor (omitiendo la parte fraccional). Una opción, como se mencionó, es hacer que cada constante sea un número de punto flotante, ya sea agregando ".0" o "f" después de él. Alternativamente, puede omitir por completo los paréntesis de la expresión más interna.Como M_PI es un número de punto flotante, y la multiplicación en C es asociativa de la izquierda (lo que significa que procede de izquierda a derecha) la primera multiplicación (2 * M_PI) se promoverá en un flotante, como lo hará cada multiplicación sucesiva. Como cos() devuelve un flotador, pNumber se le asignará un flotante sin haber realizado ninguna división entera, por lo tanto, no habrá pérdida de precisión. (Nota: generalmente no es aconsejable contar con la asociatividad o precedencia del operador, pero en este caso solo intento demostrar que de hecho funcionaría)

En cuanto al rango de números que debe esperar ver , recuerde que el coseno (sin modificar) varía de -1 a +1, no de 0 a 1, por lo que realmente verá -100 a 100 (en teoría). Para obtener el rango correcto, le gustaría agregar 1, luego multiplicar por 50.

Por cierto, los errores de compilación que obtiene en el primer caso se deben a que pi no está definido. La guía para usar M_PI es correcta: para las constantes matemáticas, siempre es más inteligente (y más consistente) usar lo que proporciona el sistema. Si tiene curiosidad, en Leopard estas constantes están # definidas en Math.h, líneas 528-540. Puede abrir el archivo usando Archivo> Abrir rápidamente ... (Cmd-Shift-D) y escribiendo "Math.h", o haciendo doble clic en M_PI en su código mientras mantiene presionado Comando.

+0

¿Cuánta precisión se requiere? ... ¿Cuál es la constante M_PI definida como? ... ¿Qué evaluaría 355/113? –

0

¿Por qué utilizar una sinusoide en primer lugar?

Si el objetivo es tener un fonction que va de 0 a 100, entonces 100 a 0 en 23 días, que puede usar:

// 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); 

También puede sustituir la x por un coseno si realmente quieres uno , como 2 * pi/23 ~ = 0.273, tiene

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