java Java中的基数方向算法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2131195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cardinal direction algorithm in Java
提问by MattyW
This weekend I spend a few minutes thrashing together an algorithm that would take in a heading (in degrees) and return a String for the cardinal direction (I'm using it in an android compass application I'm using). What I ended up with was this:
这个周末我花了几分钟时间研究一个算法,该算法将接收一个航向(以度为单位)并返回一个字符串作为主要方向(我在我正在使用的 android 指南针应用程序中使用它)。我最终得到的是这样的:
private String headingToString(Float heading)
{
String strHeading = "?";
Hashtable<String, Float> cardinal = new Hashtable<String, Float>();
cardinal.put("North_1", new Float(0));
cardinal.put("Northeast", new Float(45));
cardinal.put("East", new Float(90));
cardinal.put("Southeast", new Float(135));
cardinal.put("South", new Float(180));
cardinal.put("Southwest", new Float(225));
cardinal.put("West", new Float(270));
cardinal.put("Northwest", new Float(315));
cardinal.put("North_2", new Float(360));
for (String key: cardinal.keySet())
{
Float value = cardinal.get(key);
if (Math.abs(heading - value) < 30)
{
strHeading = key;
if (key.contains("North_"))
{
strHeading = "North";
}
break;
}
}
return strHeading;
}
My question is, is this the best way of doing this? It must have been done many times before although I haven't done a search for examples on the web yet. Have any other people tried this and found a neater solution?
我的问题是,这是最好的方法吗?虽然我还没有在网上搜索过例子,但之前肯定已经做过很多次了。有没有其他人尝试过这个并找到了更简洁的解决方案?
Edit for The Reverand's Thilo's, shinjin's and Chrstoffer's responses:
编辑 The Reverand 的 Thilo、shinjin 和 Chrstoffer 的回应:
The Solution
解决方案
public static String headingToString2(double x)
{
String directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"};
return directions[ (int)Math.round(( ((double)x % 360) / 45)) ];
}
回答by Reverend Gonzo
That's fine in most cases, though to make it optimized and (IMO) cleaner, what you could do is find a function to relate the input heading to one used in the map.
在大多数情况下这很好,但为了使其优化和(IMO)更清晰,您可以做的是找到一个函数将输入标题与地图中使用的标题相关联。
For example: (I'm pretty sure this is right, but you'll want to check it)
例如:(我很确定这是正确的,但您需要检查一下)
45* (int)Math.round(( ((double)x % 360) / 45))
What this does is first x % 360makes sure the heading is within a valid range. then
这首先x % 360确保标题在有效范围内。然后
45 * round(.../45)
finds the closest multiple of 45.
找到最接近的 45 倍数。
Now change your map to be
现在将您的地图更改为
HashMap<Integer, String> map = new HashMap<Integer, String>()
map.put(0, "North")
map.put(45, "Northeast")
etc...
So, now your algorithm becomes a fast mathemtical calculation rather than iterating through the map. Furthermore, you don't need as Hashtable here since it provides constructs for concurrency (if I remember correctly) and in your case it would actually cause a performance decrease.
所以,现在你的算法变成了快速的数学计算,而不是遍历地图。此外,您在这里不需要 as Hashtable,因为它提供了并发构造(如果我没记错的话),在您的情况下,它实际上会导致性能下降。
Once again, the performance hit may be completely negligible for your needs.
再一次,性能影响对于您的需求可能完全可以忽略不计。
Edit for Thilo's and shinjin's suggestions:
针对 Thilo 和 Shinjin 的建议进行编辑:
Instead of multiplying by 45, just keep the rest of the equation, which gives you values for 0-7, and make an array of your strings.
而不是乘以 45,只需保留等式的其余部分,即为您提供 0-7 的值,并制作一个字符串数组。
String directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"}
return directions[ (int)Math.round(( ((double)x % 360) / 45)) % 8 ]
and you've got your problem solved in two lines.
你的问题用两行解决了。
One note: Modulus won't work correctly for negative numbers. If our input heading is negative, you'll need to make it positive first.
一个注意事项:模数对于负数将无法正常工作。如果我们的输入标题为负,您需要先将其设为正。
回答by magdalar
Most of the answers here are off by 22.5 degrees for their 45 degree intervals, and map e.g. 0-45 as N, rather than [337.5-360],[0-22.5] to N. You need to offset before doing the math to correct for this.
这里的大多数答案在 45 度间隔内偏离 22.5 度,并将例如 0-45 映射为 N,而不是 [337.5-360],[0-22.5] 到 N。您需要在进行数学运算之前进行偏移对此是正确的。
Here's a solution that uses 22.5 degree intervals, such as you might see for wind directions:
这是一个使用 22.5 度间隔的解决方案,例如您可能会看到风向:
private String formatBearing(double bearing) {
if (bearing < 0 && bearing > -180) {
// Normalize to [0,360]
bearing = 360.0 + bearing;
}
if (bearing > 360 || bearing < -180) {
return "Unknown";
}
String directions[] = {
"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW",
"N"};
String cardinal = directions[(int) Math.floor(((bearing + 11.25) % 360) / 22.5)];
return cardinal + " (" + formatBearing.format(bearing) + " deg)";
}
回答by Andrei
The previous examples are not accurate, here is a more accurate solution in JavaScript.
前面的例子不准确,这里是 JavaScript 中更准确的解决方案。
function getCardinalDirection(input) {
var directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"];
var index = Math.floor( ((input-22.5)%360) / 45 );
return directions[index+1];
}
回答by Thilo
You could maybe add 15 degrees up front to avoid North_1 and North_2.
您可以在前面增加 15 度以避免 North_1 和 North_2。
回答by outaTiME
in java:
在Java中:
String _directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
public String getHeading(int hea) {
return _directions[(int)Math.floor((hea % 360) / 45)];
}
In "java" case u must need to create a Class.
在“java”的情况下,你必须需要创建一个类。
in javascript:
在 JavaScript 中:
var _directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
function getDirection (hea) {
return _directions[Math.floor((hea % 360) / 45)];
};

