最有效的方法来测试数字是否在360度圆的某个22.5度范围内

时间:2015-01-25 22:22:06

标签: java

我正在构建指南针,并且需要根据用户当前所处的22.5度间隔返回基本方向的不同字符串。

供参考,请查看this图片。

以下是我当前代码的示例:

if ((azimuth >= 348.75 && azimuth <= 360) || (azimuth >= 0 && azimuth <= 11.25))
{
    return "N";
}
else if (azimuth < 348.75 && azimuth >= 326.25)
{
    return "NNW";
}

这一系列else if语句以22.5度的间隔继续,直到涵盖所有基本方向。有没有更有效的方法来做到这一点?目前,Android Studio / IntelliJ正在显示一条错误消息this method is too complex to analyze by data flow algorithm。无论错误信息如何,我认为可能有更优雅的方式来做到这一点,但我现在无法想到它。

有什么想法吗?谢谢!

5 个答案:

答案 0 :(得分:8)

整数算术是你的朋友:

private static final POINTS = new String[]{
    "N", "NNE", "NE", "ENE", 
    "E", "ESE", "SE", "SSE",
    "S", "SSW", "SW", "WSW",
    "W", "WNW", "NW", "NNW"};

public static String point(int azimuth) {
    return POINTS[(int)((azimuth + 11.25) % 360 / 22.5)];
}

这适用于任何正值。


如果您更喜欢更直接的方法:

return new String[]{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
    "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}
    [(int)((azimuth + 11.25) % 360 / 22.5)];

答案 1 :(得分:2)

前一段时间用javascript做了一个快速解决方案:

districts = 'N;NNE;NE;ENE;E;ESE;SE;SSE;S;SSW;SW;WSW;W;WNW;NW;NNW';
districts.split(';')[Math.round(azimuth / 22.5) % 16];

不使用模16会导致错误的结果

答案 2 :(得分:0)

您想在[0; 360)内找到匹配项。 二进制搜索可以提高效率。 此外, else-if 不需要,return将提前终止该方法。

if (azimuth >= 0 && azimuth < 180) {
    if (azimuth < 90) {
        ....
    }
    else { // >= 90 and < 180
        ....
    }
}
else { // >= 180 && < 360
    ....
}

答案 3 :(得分:0)

假设azimuth总是在[0..360]之间:

if (azimuth <= 11.25) return "N";
if (azimuth <= 33.75) return "NNE";
if (azimuth <= 56.25) return "NE";
if (azimuth <= 78.75) return "ENE";
...
if (azimuth <= 348.75) return "NNW";
return "N";

警告:必须按顺序执行所有条件。

答案 4 :(得分:-1)

我认为RangeMap查找是一种更好的解决方案。您可以在Guava库中找到RangeMap实现。