Thread overview
Issue with small floating point numbers
May 13, 2021
Tim
May 13, 2021
Alain De Vos
May 13, 2021
Tim
May 13, 2021
JG
May 13, 2021
Alain De Vos
May 13, 2021
Zardoz
May 13, 2021
Berni44
May 13, 2021

Hello all,

I have this piece of code

/**
Rotate a 2D array (Vector) by phi radians

Params:
    vec = 2D Vector to rotate
    phi = Degree with which to rotate the Vector in radians

Returns:
    Rotated 2D array (Vector)

Example:

*/
pragma(inline, true)
Point2 rotate2D(in Point2 vec, in float phi) pure nothrow {
    double x = (vec[0]*cos(phi)) - (vec[1]*sin(phi));
    double y = (vec[0]*sin(phi)) + (vec[1]*cos(phi));
    return [x, y];
}

unittest{
    auto p = rotate2D([0.0, 10.0], PI_2);
    assert(p == [-10.0, 0.0]);
}

When I run the unittest, I get [-10, -4.37114e-07] back, which is obviously wrong. Any idea as to why it's not making the y-axis zero? Is it a rounding issue with the types I'm using?

Thanks in advance

May 13, 2021

Not is is not wrong it is wright.
Because you use not pi but an approximation of pi the result is not zero but an approximation of zero.

May 13, 2021

On Thursday, 13 May 2021 at 03:46:28 UTC, Alain De Vos wrote:

>

Not is is not wrong it is wright.
Because you use not pi but an approximation of pi the result is not zero but an approximation of zero.

Oh, of course. Jesus that sucks big time. Any idea on how to use assert with an approximate number like this?

May 13, 2021

On Thursday, 13 May 2021 at 03:48:49 UTC, Tim wrote:

>

On Thursday, 13 May 2021 at 03:46:28 UTC, Alain De Vos wrote:

>

Not is is not wrong it is wright.
Because you use not pi but an approximation of pi the result is not zero but an approximation of zero.

Oh, of course. Jesus that sucks big time. Any idea on how to use assert with an approximate number like this?

You could try and use this this

May 13, 2021

I would calculate the squared distance to the point (-10,0) and check it is small enough for practical use.

double squared_distance=(p.x+10) * (p.x+10)+p.y * p.y
assert (squared_distance < 1e-10);

May 13, 2021

On Thursday, 13 May 2021 at 03:03:37 UTC, Tim wrote:

>

Hello all,

I have this piece of code

/**
Rotate a 2D array (Vector) by phi radians

Params:
    vec = 2D Vector to rotate
    phi = Degree with which to rotate the Vector in radians

Returns:
    Rotated 2D array (Vector)

Example:

*/
pragma(inline, true)
Point2 rotate2D(in Point2 vec, in float phi) pure nothrow {
    double x = (vec[0]*cos(phi)) - (vec[1]*sin(phi));
    double y = (vec[0]*sin(phi)) + (vec[1]*cos(phi));
    return [x, y];
}

unittest{
    auto p = rotate2D([0.0, 10.0], PI_2);
    assert(p == [-10.0, 0.0]);
}

When I run the unittest, I get [-10, -4.37114e-07] back, which is obviously wrong. Any idea as to why it's not making the y-axis zero? Is it a rounding issue with the types I'm using?

Thanks in advance

You should try to use isClose to compare for floats equality : https://dlang.org/phobos/std_math.html#.isClose

Float arithmetic isn't exact, and could give unexpected results like 0.1f + 0.2f != 0.3f

May 13, 2021

On Thursday, 13 May 2021 at 03:03:37 UTC, Tim wrote:

>
unittest{
    auto p = rotate2D([0.0, 10.0], PI_2);
    assert(p == [-10.0, 0.0]);
}

I suggest

unittest
{
    auto p = rotate2D([0.0, 10.0], PI_2);
    assert(isClose(p[0], -10.0));
    assert(isClose(p[1], 0.0, 0.0, 1e-6));
}

In the second test, the value is compared against zero, which is somewhat special - you need to specify an acceptable distance from zero to get it right.

You could also improve your result by making the phi a double value. In this case you can replace the 1e-6 above by 1e-15 which is much closer to zero.