Objective C中的pi

34
我在iPhone编程中尝试使用pi时一直出现错误。我正在努力解决。
    float pNumber = 100*cos(2 * pi * (days/23));

但是我收到的错误信息如下:

_pi,引用自

_pi$non_lazy_ptr

我在网上看到可以使用M_PI,虽然编译通过,但我不认为它会给出正确的计算结果。

当我尝试使用:

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

我得到了0

谢谢


首先,我会将我的常量设为浮点数。 - Nosredna
4个回答

57
  • 整数除法可能需要强制转换为浮点数除法(将其中一个数字转换为double类型,或使用23.0这样的表示方法来指示您需要浮点数除法)。
  • 尝试打印出M_PI并查看它的结果(在C中使用printf(“M_PI =%16.9g \ n”,M_PI); )。
  • 您是否包含了cos()的声明?如果没有,它可能会被解释为返回整数的函数(可能需要添加#include <math.h>)。

示例代码(在Solaris 10 SPARC上使用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;
}

示例输出:

M_PI =       3.14159265
pNum =              100
pNum =      -77.5711288

在Objective-C中,如何将int转换为float? - Xcoder
2
Objective-C是C的一个完美超集(我认为),因此您可以像在C中一样进行操作。 - Nosredna
3
如果days已经是浮点数,将其强制转换为浮点数并重新赋值给同一个整型变量是没有意义的,因为它将被强制转换回整型。 - Chuck
Chucks 是对的。即使我不强制类型转换,我仍然得到 1610612736。我试图根据一个 23 天的周期得到 0 到 100 的值。 - Xcoder
4
这是一个学习调试技能的好机会。将方程拆分成较小的部分,并查看每个部分的样子。2 * M_PI *(15746/23)的结果是什么? - Nosredna
显示剩余7条评论

4

C/C++以及Objective C/C++在做普通除法时不会将整数提升为浮点数。

因此,在C/C++中,表达式15746/23的值为567,而不是你可能天真地期望的567.71207。

如果一个操作数是浮点数,C会根据需要将整数提升为浮点数,因此你只需要在表达式中使用15746.0或23.0,即更改为

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

由于 cos 返回的是浮点数(实际上是双精度浮点数,但我将忽略浮点/双精度精度问题),因此 100 将自动提升为浮点数。2 被提升为浮点数,因为 M_PI 是浮点数。15746 也被提升为浮点数,因为 23.0 是浮点数。

然而,将所有常量添加 .0 不会有任何损失,例如:

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

谢谢你的好建议,彼得。然而,我还是在做错了什么。我想要得到一个0到100之间的数字。这里有个问题,15746是自生日以来的天数。每23天,我希望得到一个值为100的峰值。如果你将12除以23,你应该得到等于0的“谷底”。所以,我想能够获取任何一天的天数,并查看它在每23天内处于1到零之间的哪个数值。两个人建议我使用这个公式来计算,但我得到的数字是15746。有什么建议吗? - Xcoder
@Robb,你能给我们展示整个程序吗?我们只看到了一行或几行代码。请提供最简单的程序,以便我们验证您所说的功能。并告诉我们您使用的C编译器和操作系统是什么。 - Nosredna
Robb,cos函数返回的结果范围为-1.0到1.0,然后你又乘以100.0,所以结果的范围必须是-100.0到100.0。因此我不明白你怎么会得到15746。实际上,以上代码将生成-77.571128。你需要发布更多的代码,最好是一个完整的示例函数。 - Peter N Lewis

1
问题在于表达式中最内层的整数除法会截断值(省略小数部分)。一种选择是将每个常量都变成浮点数,可以通过在其后添加“.0”或“f”来实现。另一种选择是完全省略最内层表达式中的括号。由于M_PI是一个浮点数,在C中乘法是从左到右结合的(即从左到右进行),第一次乘法(2 * M_PI)将被提升为浮点数,每次连续乘法也将被提升为浮点数。由于cos()返回一个浮点数,因此pNumber将被分配一个浮点数,而不需要执行任何整数除法,因此不会丢失精度。(注意:通常不明智地依赖运算符的结合性或优先级,但在这种情况下,我只是试图证明它确实有效。)
至于您应该期望看到的数字范围,要记住余弦函数(未修改)的范围是-1到+1,而不是0到1,因此您实际上会看到-100到100(理论上)。要获得正确的范围,您需要加1,然后乘以50。

顺便提一下,在第一种情况下出现的编译错误是因为未定义pi。使用M_PI的指导是正确的——对于数学常量,使用系统提供的内容总是更明智(也更一致)。如果你好奇,在Leopard上这些常量在Math.h的528-540行中被定义。你可以通过使用文件 > 快速打开...(Cmd-Shift-D)并输入“Math.h”,或者在按住Command键的同时双击你代码中的M_PI来打开该文件。


需要多少精度?M_PI常量定义为什么?355/113会评估为什么? - FrankRuperto

0

为什么首先要使用正弦波?

如果目标是在23天内拥有从0到100再到0的函数,您可以使用:

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

如果你真的想要,你也可以用余弦替换x,因为2*pi/23约等于0.273,你就有了

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接