objective-c 目标 C 中的 pi

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/978182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:42:00  来源:igfitidea点击:

pi in Objective C

iphoneobjective-c

提问by Xcoder

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

当我尝试使用 pi 时,我的 iPhone 编程一直出错。我想

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

But i get errors that say:

但我收到错误说:

_pi, referenced from

_pi,引用自

_pi$non_lazy_ptr

_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.

我在互联网上的某个地方看到使用 M_PI 并且它可以编译,但我认为它没有给我正确的计算。

When I try:

当我尝试:

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

I get 0

我得到 0

Thanks

谢谢

回答by Jonathan Leffler

  • 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_PIand 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).
  • 整数除法可能需要强制转换为浮点数(将其中一个数字转换为双精度数 - 或使用符号 23.0 表示您想要浮点除法)。
  • 尝试打印出来M_PI看看它说了什么(printf("M_PI = %16.9g\n", M_PI);在 C 中)。
  • 你是否包括声明cos()?如果不是,它可能被解释为一个返回整数的函数(#include <math.h>也许)。


Example code (tested in C on Solaris 10 SPARC with GCC 4.3.3):

示例代码(在带有 GCC 4.3.3 的 Solaris 10 SPARC 上用 C 测试):

#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

回答by Peter N Lewis

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

C/C++ 和 Objective C/C++ 在进行正常除法时不会将整数提升为浮点数。

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

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

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

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

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.

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

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

但是,将 .0 添加到所有常量不会有什么坏处,即:

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

回答by Quinn Taylor

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_PIis 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, pNumberwill 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.)

问题是表达式最里面的整数除法,它截断了值(省略了小数部分)。如前所述,一种选择是通过在其后添加“.0”或“f”使每个常量成为浮点数。或者,您可以完全省略最内层表达式中的括号。由于M_PI是一个浮点数,并且 C 中的乘法是左结合的(意味着它从左到右进行),第一个乘法 (2 * M_PI) 将被提升为浮点数,每个连续的乘法也是如此。由于cos()返回一个浮点数,pNumber将在没有执行任何整数除法的情况下分配一个浮点数,因此不会损失精度。(注意:依靠运算符结合性或优先级通常并不明智,但在这种情况下,我只是想证明它实际上可以工作。)

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.

至于您应该看到的数字范围,请记住余弦(未修改)的范围是从 -1 到 +1,而不是 0 到 1,因此您实际上会看到 -100 到 100(理论上)。要获得正确的范围,您需要加 1,然后乘以 50。

Incidentally, the compile errors you get in the first case are because piis not defined. The guidance to use M_PIis 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_PIin your code while holding down Command.

顺便说一句,您在第一种情况下遇到的编译错误是因为pi未定义。使用指南M_PI是正确的——对于数学常数,使用系统提供的东西总是更聪明(也更一致)。如果你很好奇,在 Leopard 上,这些常量在 Math.h 中 #defined,第 528-540 行。您可以使用 File > Open Quickly... (Cmd-Shift-D) 并输入“Math.h”来打开文件,或者M_PI在按住 Command键的同时双击您的代码。

回答by Léo Germond

Why use a sinusoid in the first place ?

为什么首先使用正弦曲线?

If the goal is to have a fonction ranging from 0 to 100 then 100 to 0 in 23 days, you could use:

如果目标是在 23 天内获得 0 到 100 然后 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);

You can also replace the x by a cosine if you really want one, as 2*pi/23 ~= 0.273, you have

如果你真的想要一个,你也可以用余弦替换 x,因为 2*pi/23 ~= 0.273,你有

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