我的应用可让用户搜索某个位置,其中一个查询是
"78°14'09"N 15°29'29"E"
显然,用户想要去这个位置。 首先,我如何检查此字符串是否适合十进制格式。那么如何将其转换为双重格式?
double latitude = convertToDouble("78°14'09"N")
我在这里搜索了stackoverflow,但他们都在寻找相反的结果:加倍到十进制。
答案 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;
}
这里没有错误处理,它只是一个基本的例子,说明如何使用你的输入。