简体   繁体   English

Python单元测试:测试两个角度是否几乎相等

[英]Python unittesting: Test whether two angles are almost equal

I want to test a function that outputs a heading in degrees, which is a number in the interval [0, 360). 我想测试一个以度为单位输出航向的函数,该函数是区间[0,360]中的数字。 Since the result is a floating-point number, comparing the actual result against the expected with unittest.assertEqual() does not work. 由于结果是浮点数,因此将实际结果与unittest.assertEqual()的预期结果进行比较不起作用。 unittest.assertAlmostEqual() is better since it provides a tolerance. unittest.assertAlmostEqual()更好,因为它提供了容差。 This approach works for heading that are not close to 0 degrees. 此方法适用于不接近0度的航向。

Question: What is the correct way to test for headings whose expected value is 0 degrees? 问题:测试预期值为0度标题的正确方法是什么? assertAlmostEquals() would only include angles that are slightly larger than 0 degrees, but would miss those that are slightly smaller than 0, ie 360 degrees... assertAlmostEquals()只包括略大于0度的角度,但会错过略小于0度的角度,即360度......

You can use the squared Euclidian distance between two points on the unit circle and the law of cosines to get the absolute difference between two angles: 您可以使用单位圆上两点之间的欧几里德平方距离和余弦定律来获得两个角度之间的绝对差值:

from math import sin, cos, acos
from unittest import assertAlmostEqual        

def assertAlmostEqualAngles(x, y, **kwargs):
    c2 = (sin(x)-sin(y))**2 + (cos(x)-cos(y))**2
    angle_diff = acos((2.0 - c2)/2.0) # a = b = 1
    assertAlmostEqual(angle_diff, 0.0, **kwargs)

This works with radians. 这适用于弧度。 If the angle is in degrees, you must do a conversion: 如果角度为度,则必须进行转换:

from math import sin, cos, acos, radians, degrees
from unittest import assertAlmostEqual        

def assertAlmostEqualAngles(x, y, **kwargs):
    x,y = radians(x),radians(y)
    c2 = (sin(x)-sin(y))**2 + (cos(x)-cos(y))**2
    angle_diff = degrees(acos((2.0 - c2)/2.0))
    assertAlmostEqual(angle_diff, 0.0, **kwargs)

I encountered the same situation, and found a much, much simpler solution, by taking advantage of modulo computation: 我遇到了相同的情况,并通过利用模数计算找到了一个更简单的解决方案:

In [20]: def d(a, b):
    ...:     c = (b - a) % 360
    ...:     if c > 180:
    ...:         c -= 360
    ...:     return c
    ...:

In [21]: d(1, 3)
Out[21]: 2

In [22]: d(1, 358)
Out[22]: -3

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

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