Итак, у меня возникла, как мне кажется, очень странная проблема. У меня есть грубая система для приложения усилий к объектам на 2D-плоскостях, и один из самых простых расчетов, кажется, вызывает переполнение одной из моих переменных. У меня есть следующая строка:
int ySign = m_Momentum.y / abs(m_Momentum.y);
Если у Momentum есть два элемента данных, x
y
(m_Momentum - это SFML sf :: Vector2 с плавающей точкой). Теперь обычно формула всегда должна возвращать либо 1, либо -1, в зависимости от знака Momentum.y (если я не ошибаюсь).
Однако иногда он возвращает безумно большие числа, такие как -2147483648. В этом конкретном случае значение m_Momentum.y было 0,712165 (оба значения были получены путем отправки в std :: cout); Я попытался снова, m_Momentum.y был -0,578988, а ySign был -2147483648. Существует соответствующий xSign, который также иногда всплывает, часто с тем же конечным значением. Я не могу на 100% подтвердить, что это всегда результат, но в данный момент, похоже, это так.
Я в некотором роде озадачен тем, почему это происходит, и когда это происходит, это в основном делает недействительной мою программу (она мгновенно отправляет объекты миллионами пикселей в неправильном направлении). Кажется логически невозможным, что строка выше возвращает такие странные результаты.
Ниже приведена функция, над которой я работаю. Вероятно, неправильный способ сделать это, но я не ожидал, что это пойдет так ужасно неправильно. Распечатка, которую он производит, показывает, что все числа выглядят нормальными, пока знаки не распечатаны; один из них неизменно массивный, и после этого вы видите числа типа -2,727e + 008 (что, насколько я знаю, является научным обозначением, т. е. -2,727 * 10 ^ 8).
///MODIFY MOMENTUM
//Reset, if necessary
if (Reset == true)
{
m_Momentum.x = 0;
m_Momentum.y = 0;
}
sf::Vector2<float> OldMoment = m_Momentum;
//Apply the force to the new momentum.
m_Momentum.x += Force.x;
m_Momentum.y += Force.y;
sf::Vector2<float> NewMoment = m_Momentum;
//Calculate total momentum.
float sqMomentum = m_Momentum.x * m_Momentum.x + m_Momentum.y * m_Momentum.y;
float tMomentum = sqrt(sqMomentum);
//Preserve signs for later use.
int xSign = m_Momentum.x / abs(m_Momentum.x);
int ySign = m_Momentum.y / abs(m_Momentum.y);
//Determine more or less the ratio of importance between x and y components
float xProp;
float yProp;
if (abs(tMomentum) > m_MaxVelocity)
{
//Get square of maximum velocity
int sqMax = m_MaxVelocity * m_MaxVelocity;
//Get proportion of contribution of each direction to velocity
xProp = (m_Momentum.x * m_Momentum.x) / sqMomentum;
yProp = (m_Momentum.y * m_Momentum.y) / sqMomentum;
//Reset such that the total does not exceed maximum velocity.
m_Momentum.x = sqrt(sqMax * xProp) * xSign;
m_Momentum.y = sqrt(sqMax * yProp) * ySign;
}
///SANITY CHECK
//Preserve old tMomentum
float tOld = tMomentum;
//Calculate current tMomentum
sqMomentum = m_Momentum.x * m_Momentum.x + m_Momentum.y * m_Momentum.y;
tMomentum = sqrt(sqMomentum);
//If it's still too high, print a report.
if (tMomentum > m_MaxVelocity)
{
std::cout << "\n\nSANITY CHECK FAILED\n";
std::cout << "-\n";
std::cout << "Old Components: " << OldMoment.x << ", " << OldMoment.y << "\n";
std::cout << "Force Components: " << Force.x << ", " << Force.y << "\n";
std::cout << "-\n";
std::cout << "New Components: " << NewMoment.x << ", " << NewMoment.y << "\n";
std::cout << "Which lead to...\n";
std::cout << "tMomentum: " << tOld << "\n";
std::cout << "-\n";
std::cout << "Found these proportions: " << xProp << ", " << yProp << "\n";
std::cout << "Using these signs: " << xSign << ", " << ySign << "\n";
std::cout << "New Components: " << m_Momentum.x << ", " << m_Momentum.y << "\n";
std::cout << "-\n";
std::cout << "Current Pos: " << m_RealPosition.x << ", " << m_RealPosition.y << "\n";
std::cout << "New Pos: " << m_RealPosition.x + m_Momentum.x << ", " << m_RealPosition.y + m_Momentum.y << "\n";
std::cout << "\n\n";
}
///APPLY FORCE
//To the object's position.
m_RealPosition.x += m_Momentum.x;
m_RealPosition.y += m_Momentum.y;
//To the sprite's position.
m_Sprite.Move(m_Momentum.x, m_Momentum.y);
Может кто-нибудь объяснить, что здесь происходит?
РЕДАКТИРОВАТЬ: RedX услужливо направил меня к следующему сообщению: Есть ли стандартная функция знака (signum, sgn) в C / C ++? Что побудило меня написать следующие строки кода:
//Preserve signs for later use.
//int xSign = m_Momentum.x / abs(m_Momentum.x);
//int ySign = m_Momentum.y / abs(m_Momentum.y);
int xSign = (m_Momentum.x > 0) - (m_Momentum.x < 0);
int ySign = (m_Momentum.y > 0) - (m_Momentum.y < 0);
Благодаря вышесказанному у меня больше нет странной проблемы. Для объяснения / альтернативного решения см. Пост Дидье ниже.