Inconsistency with Math.Round()

后端 未结 3 805
孤独总比滥情好
孤独总比滥情好 2021-01-20 17:11

I have two functions that are intended to contain angles between (-180,180] and (-π,π]. The intent is that given any angle from -inf to +inf it will retain the equivalent an

相关标签:
3条回答
  • 2021-01-20 17:35

    Isn't this a case for a modulo operation?

    private double Wrap180(double value)
    {
        // exact rounding of corner values
        if (value == 180) return 180.0;
        if (value == -180) return 180.0;
    
        // "shift" by 180 and use module, then shift back.
        double wrapped = ((Math.Abs(value) + 180.0) % 360.0) - 180.0;
    
        // handle negative values correctly
        if (value < 0) return -wrapped;
        return wrapped;
    }
    

    It passes this tests

        Assert.AreEqual(170.0, wrap(-190.0));
        Assert.AreEqual(180.0, wrap(-180.0));
        Assert.AreEqual(-170.0, wrap(-170.0));
        Assert.AreEqual(0.0, wrap(0.0));
        Assert.AreEqual(10.0, wrap(10.0));
        Assert.AreEqual(170.0, wrap(170.0));
        Assert.AreEqual(180.0, wrap(180.0));
        Assert.AreEqual(-170.0, wrap(190.0));
    
    0 讨论(0)
  • 2021-01-20 17:38

    It does not address the rounding issue, but here is how I would to what you want to do :

    private static double ConvertAngle(double angle)
    {
        bool isNegative = angle < 0;
        if (isNegative)
            angle *= -1;
    
        angle = angle % 360;
        if (isNegative)
            angle = -1 * angle + 360;
    
        if (angle > 180)
            angle = (angle - 360);
    
        return angle;
    }
    

    Note: This way supposes you want "behind" to be 180 degrees, not -180 degrees.

    0 讨论(0)
  • 2021-01-20 17:39

    For the angle in degrees, if x is between -180 and 180, then 180 - x is between 0 and 360. What you want is equivalent to asking that 180 - x is between 0 (inclusive), and 360 (exclusive). So, as soon as 180 - x reaches 360, we want to add 360 to the angle. This gives us:

    return angle + 360d * Math.Floor((180d - angle) / 360d);
    

    Same thing for the angle in radians:

    return angle + twopi * Math.Floor((Math.PI - angle) / twopi);
    
    0 讨论(0)
提交回复
热议问题