Итак, у меня есть то, что кажется мне очень странной проблемой. У меня есть грубая система для применения сил к объектам на 2D-плоскостях, и один из самых простых вычислений, по-видимому, вызывает переполнение одной из моих переменных. У меня есть следующие строки:Разделение поплавка самопроизвольно производит очень большие целые числа
int ySign = m_Momentum.y/abs(m_Momentum.y);
Где Momentum имеет два элемента данных, x
y
(m_Momentum является SFML научной фантастики :: 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);
Может кто-нибудь объяснить, что здесь происходит?
EDIT: RedX услужливо направил меня к следующему сообщению: Is there a standard sign function (signum, sgn) in 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);
Благодаря вышесказанному, я больше не имеют странную проблему. Для объяснения/альтернативного решения см. Сообщение Дидье ниже.
Если его просто умножение вы должны быть в состоянии производить автономный TestCase в возрасте до 10 линий. – PlasmaHH
похоже, что вы пытаетесь получить signum (или направление (+ 1/-1) в этом случае из векторного компонента? Если да, посмотрите этот поток http: // stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-cc Вы также должны прочитать: https://encrypted.google.com/url?sa=t&rct=j&q=what % 20every% 20programmer% 20should% 20know% 20about% 20floating% 20point & источник = & веб кд = 1 & вед = 0CCUQFjAA & URL = HTTP% 3A% 2F% 2Fdocs.oracle.com% 2Fcd% 2FE19957-01% 2F806-3568% 2Fncg_goldberg.html & е = -x8pT8X8I87s- gbPvMCwBQ & usg = AFQjCNHSL-lclWJrAUgNWVbQ6BAvZRoP9Q & cad = rja http://floating-point-gui.de/ – RedX
@ RedX Большое спасибо! Я использовал код верхнего ответа, и у меня больше нет проблемы. Я добавлю лучший вариант в конец моего сообщения, для дальнейшего использования. Тем не менее, мне было бы интересно узнать, почему мой код действует странно. Может быть полезным знанием в будущем. – GarrickW