如何确定一个数字是否在另一个数字的百分比范围内

5
我正在编写iPhone代码,模糊地识别滑动线是否趋近于直线。我获得了两个端点的方位角,并将其与0、90、180和270度进行比较,容忍度为正负10度。目前,我使用一堆if块来完成这个操作,这似乎非常笨拙。
如何编写一个函数,给定方位角0..360、容忍度百分比(比如20% = (-10°到+10°))和直线角度(如90度),返回方位角是否在容忍度范围内?
更新:也许我太具体了。我认为,一个好的通用函数,用于确定一个数字是否在另一个数字的百分比范围内,在许多领域都有用。
例如:数字swipeLength是否在maxSwipe的10%范围内?这将是有用的。
 BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) {
      // dunno how to calculate
 }

 BOOL result;

 float swipeLength1 = 303; 
 float swipeLength2 = 310; 

 float tolerance = 10.0; // from -5% to 5%
 float maxSwipe = 320.0;

 result = isNumberWithinPercentOfNumber(swipeLength1, tolerance, maxSwipe); 
 // result = NO

 result = isNumberWithinPercentOfNumber(swipeLength2, tolerance, maxSwipe);
 // result = YES

你理解我的意思了吗?

180度相差的角度是否有区别,例如从上到下画一条垂直线是90度,而从下到上画同一条线是270度,还是它们是相同的? - Todd Owen
1
你真的想让公差成为一个百分比吗?百分之多少?我认为一个简单的角度差异作为阈值更有意义。 - Jim Lewis
1
一个相关的问题:https://dev59.com/IUXRa4cB1Zd3GeqPvuxq(这里展示了如何计算两个向量之间的角度)。 - Todd Owen
““Is the number swipeLength within 10% of maxSwipe?" 这个问题的意思还有点不太清楚。我的理解是:“swipeLength 是否在 maxSwipe 的 90% 到 110% 范围内?”(这也是我和 Matt 回答时的假设)。但是,在你的示例中,你说 303 不应该被视为目标范围内,这只有在目标范围应该是 ±5% 的情况下才会发生(即总范围为10%),但也许你混淆了容差(对于角度)和百分比。” - Andreas F
3个回答

4
int AngularDistance (int angle, int targetAngle) 
{

    int diff = 0;
    diff = abs(targetAngle - angle)

    if (diff > 180) diff = 360 - diff;

    return diff;
}

这对于任何两个角度都应该有效。


你正在回答什么问题? - willc2
这是关于比较轴承和目标轴承(0°、90°、180°、270°)的原始问题。该函数提供了两者之间的角度,您可以将其与公差进行比较,例如10°。正如Jim Lewis所指出的那样,百分比在角度上没有太多意义,并且它们通常会更加棘手(由于它们的循环性:例如350°+20°=10°)。 - Andreas F

1

20%的十进制数等于0.2。只需除以100.0即可得到小数。除以2.0可以得到可接受范围的一半。(合并成200.0的除数)

然后,从1.0中加减来得到90%和110%的值。如果第一个数字在这些范围内,则完成了。

BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) {
      float decimalPercent = percent / 200.0;
      float highRange = secondN * (1.0 + decimalPercent);
      float lowRange = secondN * (1.0 - decimalPercent);
      return lowRange <= firstN && firstN <= highRange;
 }

注意:这里没有针对NaN或负值的错误检查。您需要为生产代码添加该功能。
更新:使百分比包括正负范围。

我没有明确说明,如果公差为20%,那么范围是从-10%到+10%。对此我深表歉意。 - willc2
好的,那就除以200.0而不是100.0。 - Matt Brunell
这个无法处理两个负数。例如,如果你传入-20和-20,它会返回false。 - rollsch

0

回答你的精炼/新问题:

bool isNumberWithinPercentOfNumber (float n1, float percentage, float n2)
{

if (n2 == 0.0) //check for div by zero, may not be necessary for float
   return false; //default for a target value of zero is false
else
   return (percentage > abs(abs(n2 - n1)/n2)*100.0);
}

简单来说,您需要取测试值和目标值之间的绝对差,并将其除以目标值(两个“abs”函数调用确保它适用于负目标和测试数字,但不适用于负百分比/公差)。这将给您以十进制小数表示的差异百分比,将其乘以100以给出“常见”的百分比表达方式(10%= 0.10),


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接