views:

7086

answers:

3
+2  Q: 

pi in Objective C

I keep getting error in my iPhone programing when I try to use pi. I'm trying

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

But i get errors that say:

_pi, referenced from

_pi$non_lazy_ptr

I saw somewhere on the internet to use M_PI and it compiles but I don't think it gives me the correct calculation.

When I try:

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

I get 0

Thanks

+9  A: 
  • The integer division probably needs to be coerced into a floating point one (cast one of the numbers to a double - or use the notation 23.0 to indicate that you want a floating point division).
  • Try printing out M_PI and see what it says (printf("M_PI = %16.9g\n", M_PI); in C).
  • Did you include the declaration for cos()? If not, it may be interpreted as a function returning an integer (#include <math.h> perhaps).


Example code (tested in C on Solaris 10 SPARC with 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;
}

Example output:

M_PI =       3.14159265
pNum =              100
pNum =      -77.5711288
Jonathan Leffler
How do you cast an int into a float in objective C?
Xcoder
Objective-C is a perfect (I think) superset of C, so you can do it the same way as in C.
Nosredna
I've tried thisdays = (float)days;float pNumber = 100*cos(2 * pi * (days/23));Still not working. I get 0. This is what I'm tring to do: http://stackoverflow.com/questions/975959/generate-a-periodic-value-based-on-dates
Xcoder
Well, you do need M_PI, unless you've assigned pi.
Nosredna
What does the declaration for days look like? And please use 100.0 for 100 and 2.0 for 2 and 23.0 for 23.
Nosredna
You mean in the header? -(float)getPhysical:(int)days
Xcoder
If days was not already a float, casting it to a float and reassigning it to the same int variable is pointless -- it will just get cast right back to an int.
Chuck
I changed to decimals and now getting 1610612736
Xcoder
Chucks right. I still get 1610612736 even when I don't cast it. I'm trying to get a value between 0 and 100 based on a cycle of 23 days.
Xcoder
What do you mean you "changed to decimals"? You mean you're using floats? What *is* the type of the variable days?
Chuck
Days is an integer that stands for the number of days since my birth. Today that number is 15746.
Xcoder
This is a great opportunity to learn some debugging skills. Break the equation down into smaller pieces and see what each piece looks like. What is the result of 2 * M_PI * (15746/23)?
Nosredna
+1  A: 

C/C++ and hence Objective C/C++ does not promote integers to floats when doing normal division.

So in C/C++ the expression 15746/23 evaluates to 567, not to 567.71207 as you might naively expect.

C will promote integers to floats as necessary if one or other operand is a float, so all you need to do is use 15746.0 or 23.0 in your expression, ie change to

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

The 100 will automatically be promoted because cos returns a float (actually a double, but I will ignorefloat/double percissions issues). The 2 is promoted to a float because M_PI is a float. And the 15746 is promoted to a float because 23.0 is a float.

However, it would not hurt to add the .0 to all the constants, ie:

float pNumber = 100.0*cos(2.0 * M_PI * (15746.0/23.0));
Peter N Lewis
Thanks for the great suggestion Peter however, I'm still doing something wrong. I'm trying to get a number between 0 and 100. Here is the deal, 15746 is the number of days since a birthday. Every 23 days I want a peak of 100. if you divide 12 you should get "valley" that is equal to 0. So, I want to be able to get the number of days of any given day and see what number it is between 1 and zero based on every 23 days. This formula was recommend as the way to find it by two people, yet i'm getting the number 15746. Any suggestions?
Xcoder
@Robb how about you show us the whole program? We're just seeing a line here and there. Give us the smallest program that does what you say it does. And tell us what your C compiler is and what OS you're running.
Nosredna
Robb, cos returns a result with a range of -1.0 to 1.0, and you are then multiplying by 100.0, so the result must have a range of -100.0 to 100.0. So I can't see how you can be getting 15746. Indeed, the above will generate -77.571128. You will have to post more code, preferably a complete example function.
Peter N Lewis
A: 

The problem is the integer division in the innermost part of the expression, which truncates the value (omitting the fractional part). One option, as mentioned, is to make every constant a floating point number, either by adding ".0" or "f" after it. Alternatively, you can omit the parentheses from the innermost expression entirely. Since M_PI is a floating point number, and multiplication in C is left-associative (meaning it proceeds from left to right) the first multiplication (2 * M_PI) will be promoted to a float, as will each successive multiply. Since cos() returns a float, pNumber will be assigned a float without having performed any integer division, hence no loss of precision. (Note: It's not usually wise to count on operator associativity or precedence, but in this case I'm just trying to demonstrate that it would in fact work.)

As far as the range of numbers you should expect to see, recall that the cosine (unmodified) ranges from -1 to +1, not 0 to 1, so you would actually see -100 to 100 (in theory). To get the correct range, you'd want to add 1, then multiply by 50.

Incidentally, the compile errors you get in the first case are because pi is not defined. The guidance to use M_PI is correct — for math constants, it's always smarter (and more consistent) to use what the system provides. If you're curious, on Leopard these constants are #defined in Math.h, lines 528-540. You can open the file by using File > Open Quickly... (Cmd-Shift-D) and typing "Math.h", or by double-clicking on M_PI in your code while holding down Command.

Quinn Taylor