简体   繁体   English

通过自己划分浮点产生非常大的整数

[英]Dividing a Float by Itself Produces Very Large Integers

So I'm having what seems to me to be a very bizarre problem. 所以我觉得在我看来这是一个非常奇怪的问题。 I've got a crude system for applying forces to objects on 2D planes, and one of the simplest calculations seems to be causing one of my variables to overflow. 我有一个粗略的系统,用于在2D平面上对物体施加力,其中一个最简单的计算似乎是导致我的一个变量溢出。 I have the following line: 我有以下几行:

int ySign = m_Momentum.y / abs(m_Momentum.y);

Where Momentum has two data members, x y (m_Momentum is an SFML sf::Vector2 of floats). Momentum有两个数据成员, x y (m_Momentum是浮点数的SFML sf :: Vector2)。 Now, normally the formula should always return either 1 or -1, depending on the sign of Momentum.y (unless I'm grossly mistaken). 现在,通常公式应该总是返回1或-1,这取决于Momentum.y的符号(除非我非常错误)。

However, it occasionally returns insanely high numbers such as -2147483648. 然而,它偶尔会返回极其高的数字,如-2147483648。 In that particular case, the value of m_Momentum.y was 0.712165 (both values were obtained by sending to std::cout); 在那种特殊情况下,m_Momentum.y的值是0.712165(两个值都是通过发送到std :: cout获得的); I tried again, m_Momentum.y was -0.578988 and ySign was still -2147483648. 我再次尝试,m_Momentum.y是-0.578988,而ySign仍然是-2147483648。 There is a corresponding xSign that also flips out sometimes, often with the same final value. 有一个相应的xSign有时会翻转,通常具有相同的最终值。 I can't confirm 100% that this is always the result, but at the moment that seems to be the case. 我不能100%确认这总是结果,但目前似乎是这种情况。

I'm sort of stumped as to why this is happening, and when it does, it basically invalidates my program (it instantly sends objects millions of pixels in the wrong direction). 我有点难以理解为什么会这样,当它发生时,它基本上使我的程序无效(它会立即向错误的方向发送数百万像素的对象)。 It seems logically impossible that the line above is returning such strange results. 从逻辑上看,上面的这一行似乎不可能返回如此奇怪的结果。

Below is the function I am working on. 以下是我正在处理的功能。 Probably the wrong way to do it, but I didn't expect it to go so horribly wrong. 可能是错误的做法,但我没想到会出现如此可怕的错误。 The printout it produces reveals that all numbers look normal until the signs are printed out; 它产生的打印输出显示所有数字看起来都正常,直到打印出标志; one of them is invariably massive, and afterwards you see numbers like -2.727e+008 (which, as far as I'm aware, is scientific notation - ie -2.727 * 10 ^ 8). 其中一个总是很大,然后你会看到像-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);

Can somebody explain what's going on here? 有人能解释一下这里发生了什么吗?

EDIT: RedX helpfully directed me to the following post: Is there a standard sign function (signum, sgn) in C/C++? 编辑:RedX帮我指导了以下帖子: C / C ++中是否有标准符号函数(signum,sgn)? Which led me to write the following lines of code: 这让我编写了以下几行代码:

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

Thanks to the above, I no longer have the strange problem. 由于上述原因,我不再有这个奇怪的问题。 For an explanation/alternative solution, see Didier's post below. 有关解释/替代解决方案,请参阅下面的Didier的帖子。

You should use fabs() instead of abs() to get the absolute value of a floating point number. 您应该使用fabs()而不是abs()来获取浮点数的绝对值。 If you use the integer absolute function, then the result is an integer ... 如果使用整数绝对函数,则结果为整数...

For instance, -0.5 / abs(-0.5) is treated as -0.5 / 0 which results in negative infinity (as a floating point value) that is converted to the minimum value of an int 0x80000000 = -2147483648 例如, -0.5 / abs(-0.5)被视为-0.5 / 0 ,这导致负无穷大(作为浮点值)被转换为int的最小值0x80000000 = -2147483648

Taking absolute values and dividing sounds like an awful waste of cycles to me. 采用绝对值和划分声音对我来说是一种可怕的浪费。 What's wrong with 怎么了?

x > 0 ? 1 : -1

which you could always put in a function 你可以随时放入一个功能

template <class T>
inline int sgn(const T &x) { return x > 0 ? : 1; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM