A.Pissicat
A.Pissicat

Reputation: 3285

C++ different values between variables and debugger

I'm working in C++ with Visual Studio.

I got a strange case. There is my code (simplified version) :

Point GetPoint(/*parameters*/)
{
    float Ax = 149; //Value depending on parameters
    float Ay = 20;
    float Bx = 29;
    float By = 19;
    double pAB = (Ay - By) / (Ax - Bx);
    double Sx = Cx;
    double Sy = pAB * (Cx - Ax) + Ay;
    // Sy = (20 - 19) / (149 - 29) * (29 - 149) + 20.0
    // => Sy = 1 / 120 * -120 + 20
    // => Sy = -1 + 20
    
    return new Point(static_cast<int>(Sx), static_cast<int>(Sy));
}

I expected that Sy = 19 but instead my point value is 18. I started the debugger to understand and I found this :

(Ay - By) / (Ax - Bx) = 0.00833333284

(20.0 - 19.0) / (149.0 - 29.0) = 0.0083333333333333332

pAB = 0.0083333337679505348

And :

(20.0 - 19.0) / (149.0 - 29.0) * (29.0 - 149.0) + 20.0 = 19

Sy = 18.999999947845936

Final cast set my point to 18 (sy < 19). But the same code in C# give me a 19. Why theses difference ? And how can I get a 19 ?

Upvotes: 1

Views: 111

Answers (1)

C++ and C# are different languages, with different rules and different compilers. Since floating point is inexact by definition, any subtle difference can result in the different values you see.

I don't know the C# rules at all, but in C++, notice that while you have typed pAB as double, you're actually computing its value in float (because Ax, Ay, Bx, By are all floats) and only after that is the value promoted to a double. In other words, you do not gain any precision here by using double. Maybe the C# rules are different here, no idea.

Anyway, if you make sure pAB is computed in double, you get exact values with these particular numbers: [live example], compared to [the unchanged code].

Making sure the double value is actually computed in double is probably the correct solution here. Nevertheless, since floating point is inexact and could "fail" for you with other values, I suggest using std::round instead of casting to int if you want rounding behaviour.

Upvotes: 1

Related Questions