Java中的主方向算法 [英] Cardinal direction algorithm in Java

查看:145
本文介绍了Java中的主方向算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这周末,我花了几分钟颠簸起来的算法,将采取在标题(度),并返回一个字符串的基本方向(我用它在我使用的是Android的指南针应用程序)。我结束了是这样的:

 私人字符串headingToString(浮动航向)
{
    字符串strHeading =?;
    哈希表<字符串,浮法>基数=新的Hashtable<字符串,浮法>();
    cardinal.put(North_1,新的浮动(0));
    cardinal.put(东北,新的浮动(45));
    cardinal.put(东,新的浮动(90));
    cardinal.put(东南,新的浮动(135));
    cardinal.put(南方,新的浮动(180));
    cardinal.put(西南,新的浮动(225));
    cardinal.put(西部大开发,新的浮动(270));
    cardinal.put(西北,新的浮动(315));
    cardinal.put(North_2,新的浮动(360));

    对于(字符串键:cardinal.keySet())
    {
        浮动值= cardinal.get(密钥);
        如果(Math.abs(品目 - 值)小于30)
        {
            strHeading =键;
            如果(key.contains(North_))
            {
                strHeading =北;
            }
            打破;
        }
    }
    返回strHeading;
}
 

我的问题是,这是这样做的最好方法是什么?它必须以前我虽然没有做过搜索网络上的例子尚未做过很多次。有其他人尝试这样做,发现了一个更简洁的解决方案?

修改为Reverand的蒂洛的,shinjin的和Chrstoffer的反应:

解决方案

 公共静态字符串headingToString2(双X)
{
    串方向[] = {N,东北,E,SE,S,SW,W,西北,N};
    返回方向[(INT)Math.round((((双)×360%)/ 45));
}
 

解决方案

这很好,在大多数情况下,虽然让IT优化和(IMO)清洁剂,你可以做的是找到相关的输入标题中使用的一个功能在地图上。

例如: (我是pretty的肯定,这是对的,但你要检查它)

  45 *(INT)Math.round((((双)×360%)/ 45))
 

这样做是第一个 X%360 确保标题是有效范围内。那么

  45 *圆(... / 45)
 

发现的45最接近多个

现在改变你的地图是

 的HashMap<整数,字符串>图=新的HashMap<整数,字符串>()
  map.put(0,北)
  map.put(45,东北)
  等等...
 

所以,现在你的算法成为一个快速mathemtical计算,而不是通过地图迭代。此外,你不需要为Hashtable的位置,因为它提供了构建并发(如果我没记错的话),并在你的情况下,它实际上会导致性能下降。

再次,性能损失可能是完全可以忽略不计满足您的需求。

编辑为蒂洛的和shinjin的建议:

相反,45乘以,只是不停的公式,它给你的0-7值的休息,让你的字符串数组。

 字符串方向[] = {N,东北,E,SE,S,SW,NW}
返回方向[(INT)Math.round((((双)×360%)/ 45))]
 

和你有两行的问题就解决了​​。

一注:为负数模量将无法正常工作。如果我们输入标题是否定的,你需要使它积极的第一次。

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:

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

解决方案

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.

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 % 360 makes sure the heading is within a valid range. then

45 * round(.../45)

finds the closest multiple of 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.

Once again, the performance hit may be completely negligible for your needs.

Edit for Thilo's and shinjin's suggestions:

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.

String directions[] = {"N", "NE", "E", "SE", "S", "SW", "NW"}
return directions[ (int)Math.round((  ((double)x % 360) / 45)) ]

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.

这篇关于Java中的主方向算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆