【问题标题】:How do I determine whether a number is within a percentage of another number如何确定一个数字是否在另一个数字的百分比范围内
【发布时间】:2025-12-04 21:20:07
【问题描述】:

我正在编写 iPhone 代码,它可以模糊地识别刷过的线是否是直线。我得到两个端点的方位,并将其与 0、90、180 和 270 度进行比较,公差为正负 10 度。现在我用一堆 if 块来做这件事,看起来超级笨重。

如何编写一个函数,给定 bearing 0..360,tolerance 百分比(比如 20% = (-10° 到 +10°))和一个像90度这样的直角度,返回轴承是否在公差范围内?

更新: 也许我太具体了。我认为一个很好的通用函数可以确定一个数字是否在另一个数字的百分比范围内很多领域。

例如:数字 swipeLength 是否在 ma​​xSwipe10% 范围内?那会很有用。

 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 绘制的同一条线,还是它们相同?
  • 你真的是说容忍度是一个百分比吗?百分之几?我认为一个简单的角度差异作为阈值更有意义。
  • 一个相关问题:*.com/questions/338762/…(这显示了如何计算两个向量之间的角度)。
  • “swipeLength 的数字是否在 maxSwipe 的 10% 范围内?”的意思还有些不清楚。我将其解释为:“swipeLength 是否在 maxSwipe 的 90% 到 maxSwipe 的 110% 的范围内?” (这也是我的第二个答案和马特的答案所假设的)。但是,在您的示例中,您说不应将 303 视为在您的目标范围内,只有当您的目标范围应为 maxSwipe 的 +/- 5%(即总范围为 10%)时才会出现这种情况,但是也许您将公差(角度)与百分比混淆了。

标签: math angle gesture-recognition fuzzy-comparison


【解决方案1】:
int AngularDistance (int angle, int targetAngle) 
{

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

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

    return diff;
}

这应该适用于任何两个角度。

【讨论】:

  • 你在回答什么问题?
  • 这是关于将轴承与目标轴承(0°、90°、180°、270°)进行比较的原始问题。该函数为您提供两者之间的角度,您可以将其与您的公差进行比较,比如说 10° 正如 Jim Lewis 指出的那样,百分比对角度没有意义,而且它们通常有点棘手(由于它们的圆度:例如 350° + 20° = 10°)。
【解决方案2】:

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%。我很抱歉。
  • 好吧,那就除以 200.0 而不是 100.0。
  • 这不适用于两个负数。例如,如果你传入 -20 和 -20,它会返回 false。
【解决方案3】:

回答您的提炼/新问题:

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);
}

为了解释,您将测试值和目标值之间的绝对差除以目标值(两个“绝对”调用确保这也适用于负目标和测试数字,但不适用于负百分比/公差)。这为您提供了以小数表示的差异百分比,将其乘以 100 以给出百分比的“常见”表达式 (10% = 0.10),

【讨论】:

    最近更新 更多