如何将以度数分钟秒为单位的位置转换为字符串表示为Double

时间:2016-07-01 18:27:10

标签: java gps location decimalformat

我的应用可让用户搜索某个位置,其中一个查询是

"78°14'09"N 15°29'29"E"

显然,用户想要去这个位置。 首先,我如何检查此字符串是否适合十进制格式。那么如何将其转换为双重格式?

double latitude = convertToDouble("78°14'09"N")

我在这里搜索了stackoverflow,但他们都在寻找相反的结果:加倍到十进制。

4 个答案:

答案 0 :(得分:0)

您无法在不删除非数字字符的情况下将其解析为双精度,但

String string =  "78°14'09"N";  
Double number = 0;
 try{
       number = Double.parseDouble(string);
                //do something..
    }catch (NumberFormatException e){
       //do something.. can't be parsed
    }

答案 1 :(得分:0)

如果您首先从字符串中删除非字母数字的任何字符,那么这些行中的某些内容将起作用。这段代码编译。

public class HelloWorld{

     public static void main(String []args){
        String input = "78 14'09 N 15 29'29 E".replaceAll("[^A-Za-z0-9]", " ");
        String[] array = input.split(" ");

        int nDegree = Integer.parseInt(array[0]);
        int nMinute = Integer.parseInt(array[1]);
        int nSecond = Integer.parseInt(array[2]);

        int eDegree = Integer.parseInt(array[4]);
        int eMinute = Integer.parseInt(array[5]);
        int eSecond = Integer.parseInt(array[6]);

        double nDegrees = nDegree + (double) nMinute/60 + (double) nSecond/3600;
        double eDegrees = eDegree + (double) eMinute/60 + (double) eSecond/3600;

        String nResult = "Decimal = N " + Double.toString(nDegrees).substring(0,10);
        String eResult = "Decimal = E " + Double.toString(eDegrees).substring(0,10);

        System.out.println(nResult);
        System.out.println(eResult);
     }
}

输出:

Decimal = N 78.2358333
Decimal = E 15.4913888

问题是Java无法将度°字符存储为字符串或内部引号(分钟字符)的一部分。如果你能在输入数据之前找到一种从字符串中删除它们的方法,那么这将有效。

我没有处理度数符号的解决方案,但您可以使用转义符号\"来允许在字符串中使用引号。

答案 2 :(得分:0)

78°14'09"N 15°29'29"E
     

首先,如何正确检查此字符串是否符合十进制格式。那么如何将其转换为双重格式?

字符串是十进制(度)格式的 。它以度,分和秒为单位,或多或少与十进制度格式相反。因此,我将您解释为您要测试字符串是否为有效的D / M / S格式,如果是,则将其转换为十进制度,表示为一对double s。

这主要是一个解析问题,正则表达式通常对简单的解析问题很有用,比如这个问题。合适的正则表达式既可以检查格式,也可以捕获需要提取的数字部分。这是创建这种模式的一种方法:

    private final static Pattern DMS_PATTERN = Pattern.compile(
            "(-?)([0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([NS])\\s*" +
            "(-?)([0-1]?[0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([EW])");

我承认,这有点密集。如果您不熟悉正则表达式,那么这不是完整解释的地方; API docs for Pattern提供概述,您可以在很多地方找到教程。如果您发现输入符合此模式,那么您不仅要验证格式,还要解析出转换为十进制度的正确部分。

基本公式为decimal = degrees + minutes / 60 + seconds / 3600。你有一个额外的复杂性,坐标'来自赤道/本初子午线的方向可能通过N / S,E / W或有符号N,E或两者的组合来表达。上述模式适用于所有这些替代方案。

总而言之,您可能会这样做:

    private double toDouble(Matcher m, int offset) {
        int sign = "".equals(m.group(1 + offset)) ? 1 : -1;
        double degrees = Double.parseDouble(m.group(2 + offset));
        double minutes = Double.parseDouble(m.group(3 + offset));
        double seconds = Double.parseDouble(m.group(4 + offset));
        int direction = "NE".contains(m.group(5 + offset)) ? 1 : -1;

        return sign * direction * (degrees + minutes / 60 + seconds / 3600);
    }

    public double[] convert(String dms) {
        Matcher m = DMS_PATTERN.matcher(dms.trim());

        if (m.matches()) {
            double latitude = toDouble(m, 0);
            double longitude = toDouble(m, 4);

            if ((Math.abs(latitude) > 90) || (Math.abs(longitude) > 180)) {
                throw new NumberFormatException("Invalid latitude or longitude");
            }

            return new double[] { latitude, longitude };
        } else {
            throw new NumberFormatException(
                    "Malformed degrees/minutes/seconds/direction coordinates");
        }
    }

convert()方法是主要方法;它将坐标返回为两个double s的数组,表示赤道与本初子午线交叉点北和东的十进制度坐标。在赤道以南的纬度表示为负的,在本初子午线以西的经度也是如此。如果输入与模式不匹配,或者如果经度表示的纬度或经度无效(经度的大小不能超过180°;纬度不能超过90°),则抛出NumberFormatException

答案 3 :(得分:0)

所以我使用带有捕获组的正则表达式来获取每个数字和N / S / E / W.在单独捕获每个之后,只需要进行一些划分来获取数字,然后根据您的喜好格式化它们。例如,我在这里使用了5位精度。

public static void main(String[] args) {
    String coords = "78°14'09N 15°29'29E";
    String[] decimalCoords = degreesToDecimal(coords);

    System.out.println(decimalCoords[0]);
    System.out.println(decimalCoords[1]);
}

public static String[] degreesToDecimal(String degMinSec) {
    String[] result = new String[2];
    Pattern p = Pattern.compile("(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?");
    Matcher m = p.matcher(degMinSec);

    if (m.find()) {
        int degLat = Integer.parseInt(m.group(1));
        int minLat = Integer.parseInt(m.group(2));
        int secLat = Integer.parseInt(m.group(3));
        String dirLat = m.group(4);
        int degLon = Integer.parseInt(m.group(5));
        int minLon = Integer.parseInt(m.group(6));
        int secLon = Integer.parseInt(m.group(7));
        String dirLon = m.group(8);

        DecimalFormat formatter = new DecimalFormat("#.#####", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
        formatter.setRoundingMode(RoundingMode.DOWN);

        result[0] = formatter.format(degLat + minLat / 60.0 + secLat / 3600.0) + " " + dirLat;
        result[1] = formatter.format(degLon + minLon / 60.0 + secLon / 3600.0) + " " + dirLon;
    }
    return result;
}

这里没有错误处理,它只是一个基本的例子,说明如何使用你的输入。