#c
Вопрос:
этот код делит окружность на X частей и отображает таблицу значений радиана каждой части. но я получаю бесконечный цикл отображения 0, когда я использую значение, превышающее 6, со значением ниже 6 я получаю «0 1 2 3 4 5 6». Кажется, что отображаемое значение также не является плавающим. У меня есть код, использующий степени, и он отлично работает.
#include <iostream>
using namespace std;
#define pi 3.14159265359
#define pi2 6.28318530718
int nbObjets = 0;
void objetsPositionRadian(int tab[], int nbObjets);
int main(){
int tabRadian[] = {0};
std::cout << "Nombre d'objets ? ";
std::cin >> nbObjets;
objetsPositionRadian(tabRadian, nbObjets);
return 0;
}
void objetsPositionRadian(int tab[], int nbObjets){
float radian = (360/nbObjets) * (pi/180);
for (int i = 0; i < pi2; i =radian){
std::cout << i << " ";
}
std::cout << endl;
}
Комментарии:
1.
i =radian
добавляетfloat
меньше 1 кint
, это ничего не даст.2. спасибо, это была моя ошибка, теперь работает нормально
3. У вас та же основная проблема в другом месте. Если вы запросите более 360 объектов,
(360 / nbObjets)
это станет нулем, и вы снова получите бесконечный цикл. Изменение360
на360.0
должно исправить это.4. Независимо от того, работает ли он «нормально»,
for
цикл должен использовать целые числа, а не плавающую точку в качестве условий начала / продолжения / остановки. Причина в том, что ваш цикл не будет гарантированно повторяться столько раз, сколько вы ожидаете, если вы используете переменные цикла с плавающей запятой. Если вам нужноn
время цикла, тоi
следует перейти от0
кn
и внутри цикла масштабироватьi
значение до значения с плавающей точкой , которое вы хотите использовать.5. Работать в градусах приятно, потому что 360 делится равномерно на множество разных целых чисел.
Ответ №1:
Очевидный ход здесь состоит в том, чтобы изменить i
свой цикл на a double
(или float
) вместо an int
.
Наряду с этим при вычислении radian
360/nbObjets
выполняется целочисленное деление, поэтому, если nbObjets
значение > 360, оно даст результат 0. Изменение 360
на 360.0
исправляет эту проблему.
Но это оставляет еще одну проблему: в зависимости от причуд математики с плавающей запятой, если вы запросите много объектов, есть хорошие изменения, которые приведут к вычислению позиций для одного объекта больше, чем вы просили (и, возможно, даже больше, если вы запросили действительно большое количество объектов).
Эта проблема возникает из-за кумулятивных ошибок при добавлении radian
i
в цикл. Вместо того, чтобы делать это, вы почти наверняка хотите что-то в этом заказе:
for (int i=0; i<nbObjets; i )
cout << i * radian;
Таким образом, вы всегда получаете именно то количество объектов, которое вы просили, и любые возможные ошибки в значении не накапливаются от одной итерации к следующей.
Комментарии:
1. ваше решение кажется более стабильным с проблемой поплавка, разве double тоже не дает достаточной точности ?
2. @CTRL-Z: в зависимости от количества объектов
double
может быть достаточно просто использовать. Навскидку я немного не уверен, сколько именно объектов у вас может быть, прежде чем все пойдет не так.3. теперь, когда я осознаю эту нестабильную ситуацию, я думаю, что ваше решение-лучшее решение.
4. @CTRL-Z: Конечно.
5. @CTRL-Z
double
имеет большую точность, чемfloat
так что это почти всегда лучший выбор.
Ответ №2:
Вы делаете две опасные вещи в следующих двух строках:
float radian = (360/nbObjets) * (pi/180);
for (int i = 0; i < pi2; i =radian)
Во-первых: nbObject
определяется как целое число. В результате 360/nbObjects
будет вычислено целое число (например, для 7 результатом будет 51, а не число с плавающей запятой).
Затем вы определяете i
как целое число. Когда вы добавляете к нему число, меньшее 1, оно всегда будет оставаться неизменным.
Поэтому я советую вам при необходимости использовать больше чисел с плавающей запятой, как в этом предложении:
double radian = ((double)360/nbObjets) * (pi/180); // first typecast 360 as a
// floating point, in order
// to enforce floating
// point arithmetic.
for (double i = 0; i < pi2; i =radian)
Это должно работать лучше.
Комментарии:
1. Это страдает от состояния, упомянутого в комментариях. Нет никакой гарантии, что цикл всегда будет повторяться одно и то же количество раз из-за неточности с плавающей запятой.
2. @PaulMcKenzie: Он всегда должен повторяться одно и то же количество раз при каждом запуске. Плавающие точки детерминированы, просто… не интуитивно. О, ты имел в виду повторение цикла столько же раз, сколько и раньше? Это правда
3. @MooingDuck: В этом случае я бы сказал, что важным моментом является то, что количество результатов, которые вы получаете, может не соответствовать количеству объектов, для которых вы попросили его вычислить позиции.
4. @MooingDuck Изменение параметров компилятора / компилятора может привести к различным результатам с точки зрения количества выполняемых итераций.
5. спасибо за вашу помощь, я искал в неправильном направлении.