пи в цель C - PullRequest
       11

пи в цель C

31 голосов
/ 11 июня 2009

Я постоянно получаю сообщение об ошибке при программировании iPhone, когда пытаюсь использовать пи. Я пытаюсь

    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

Спасибо

Ответы [ 4 ]

55 голосов
/ 11 июня 2009
  • Целочисленное деление, вероятно, нужно привести к единице с плавающей точкой (приведите одно из чисел к двойному - или используйте нотацию 23.0, чтобы указать, что вы хотите деление с плавающей запятой).
  • Попробуйте распечатать M_PI и посмотрите, что там написано (printf("M_PI = %16.9g\n", M_PI); в C).
  • Вы включили декларацию для cos()? Если нет, то это может быть интерпретировано как функция, возвращающая целое число (возможно, #include <math.h>).

Пример кода (проверено в C на 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
4 голосов
/ 11 июня 2009

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

100 будет автоматически повышен, потому что cos возвращает число с плавающей запятой (на самом деле это double, но я буду игнорировать проблемы с float / double percissions). 2 переводится в число с плавающей точкой, потому что M_PI является числом с плавающей точкой. А 15746 повышен до плавающего, потому что 23,0 - это плавающее.

Однако не мешало бы добавить .0 ко всем константам, то есть:

float pNumber = 100.0*cos(2.0 * M_PI * (15746.0/23.0));
1 голос
/ 11 июня 2009

Проблема заключается в целочисленном делении во внутренней части выражения, которое усекает значение (исключая дробную часть). Один из вариантов, как уже упоминалось, состоит в том, чтобы сделать каждую константу числом с плавающей запятой, добавив после нее «.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. Вы можете открыть файл, используя File> Open Quickly ... (Cmd-Shift-D) и набрав "Math.h", или дважды щелкнув по M_PI в своем коде, удерживая Command.

0 голосов
/ 09 марта 2011

Зачем в первую очередь использовать синусоиду?

Если цель состоит в том, чтобы иметь функцию в диапазоне от 0 до 100, а затем от 100 до 0 в течение 23 дней, вы можете использовать:

// 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...