如何将以字符串表示的度分秒位置转换为双精度

Mar*_*lon 2 java gps location decimalformat

我的应用程序允许用户搜索位置,我收到的查询之一是

\n\n
"78\xc2\xb014\'09"N 15\xc2\xb029\'29"E"\n
Run Code Online (Sandbox Code Playgroud)\n\n

显然用户想要转到这个位置。\n首先如何检查该字符串是否正确符合十进制格式。那么如何将其转换为双精度格式呢?

\n\n
double latitude = convertToDouble("78\xc2\xb014\'09"N")\n
Run Code Online (Sandbox Code Playgroud)\n\n

我在 stackoverflow 上搜索过,但他们都在寻找相反的内容:双精度到十进制。

\n

Joh*_*ger 5

\n
78\xc2\xb014\'09"N 15\xc2\xb029\'29"E\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

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

\n

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

\n
    private final static Pattern DMS_PATTERN = Pattern.compile(\n            "(-?)([0-9]{1,2})\xc2\xb0([0-5]?[0-9])\'([0-5]?[0-9])\\"([NS])\\\\s*" +\n            "(-?)([0-1]?[0-9]{1,2})\xc2\xb0([0-5]?[0-9])\'([0-5]?[0-9])\\"([EW])");\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

基本公式是decimal = degrees + minutes / 60 + seconds / 3600。您还有一个额外的复杂问题,即赤道/本初子午线的坐标方向可以通过 N/S、E/W 或带符号的 N、E 或两者的组合来表示。上述模式适应了所有这些替代方案。

\n

把它们放在一起,你可能会做这样的事情:

\n
    private double toDouble(Matcher m, int offset) {\n        int sign = "".equals(m.group(1 + offset)) ? 1 : -1;\n        double degrees = Double.parseDouble(m.group(2 + offset));\n        double minutes = Double.parseDouble(m.group(3 + offset));\n        double seconds = Double.parseDouble(m.group(4 + offset));\n        int direction = "NE".contains(m.group(5 + offset)) ? 1 : -1;\n\n        return sign * direction * (degrees + minutes / 60 + seconds / 3600);\n    }\n\n    public double[] convert(String dms) {\n        Matcher m = DMS_PATTERN.matcher(dms.trim());\n\n        if (m.matches()) {\n            double latitude = toDouble(m, 0);\n            double longitude = toDouble(m, 5);\n\n            if ((Math.abs(latitude) > 90) || (Math.abs(longitude) > 180)) {\n                throw new NumberFormatException("Invalid latitude or longitude");\n            }\n\n            return new double[] { latitude, longitude };\n        } else {\n            throw new NumberFormatException(\n                    "Malformed degrees/minutes/seconds/direction coordinates");\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n