0

We are doing the following exercise: Sexagesimal degree. We would like to convert a decimal input, for example

lat: 48.858222
lon: 2.2945

to a sexagesimal result as:

48° 51′ 30″ N, 2° 17′ 40″ E

We have written the following code:

import java.util.*;
public class SexagesimalDegree {

  /**
   * Convert WGS84-Coordinates from decimal degrees in sexagesimal degrees
   * 
   * @param lat Latitute as Double
   * @param lon Longtitute as Double
   * @return String "%d° %d′ %d″ %s, %d° %d′ %d″ %s" (lat_degree, lat_minute, lat_second, lat_direction,
   *                                                  lon_degree, lon_minute, lon_second, lon_direction)
   * @throws Exception 
   */
  public static String convert /**/ (double lat, double lon) throws Exception {
    System.out.println("lat: "+lat);
    System.out.println("lon: "+lon);
    String[] latSplitted = String.valueOf(lat).split("\\.");
    String[] lonSplitted = String.valueOf(lon).split("\\.");
    System.out.println("latSplitted: "+Arrays.toString(latSplitted));
    System.out.println("lonSplitted: "+Arrays.toString(lonSplitted));
    String latHours = latSplitted[0];
    String lonHours = lonSplitted[0];
    System.out.println("latHours: "+latHours);
    System.out.println("lonHours: "+lonHours);

    double latMinutesNumber = Double.parseDouble(latSplitted[1])*60;
    double lonMinutesNumber = Double.parseDouble(lonSplitted[1])*60;
    System.out.println("latMinutesNumber: "+latMinutesNumber);
    System.out.println("lonMinutesNumber: "+lonMinutesNumber);


    String latMinutes = String.valueOf((int)(latMinutesNumber)).substring(0,2);
    String lonMinutes = String.valueOf((int)(lonMinutesNumber)).substring(0,2);
    System.out.println("latMinutes: "+latMinutes);
    System.out.println("lonMinutes: "+lonMinutes);

    String latDecimalPart = "0"+String.valueOf(latMinutesNumber).substring(String.valueOf(latMinutesNumber).indexOf("."));
    String lonDecimalPart = "0"+String.valueOf(lonMinutesNumber).substring(String.valueOf(lonMinutesNumber).indexOf("."));
    System.out.println("latDecimalPart: "+latDecimalPart);
    System.out.println("lonDecimalPart: "+lonDecimalPart);

    System.out.println("Double.parseDouble(latDecimalPart): "+Double.parseDouble(latDecimalPart));

    double remainingLatSeconds = Integer.parseInt(latMinutes)-Double.parseDouble(latDecimalPart);
    System.out.println("remainingLatSeconds: "+remainingLatSeconds);

    return "";
  }
}

Which outputs the following results:

lat: 48.858222
lon: 2.2945
latSplitted: [48, 858222]
lonSplitted: [2, 2945]
latHours: 48
lonHours: 2
latMinutesNumber: 5.149332E7
lonMinutesNumber: 176700.0
latMinutes: 51
lonMinutes: 17
latDecimalPart: 0.149332E7
lonDecimalPart: 0.0
Double.parseDouble(latDecimalPart): 1493320.0
remainingLatSeconds: -1493269.0

As you would notice we are able to get hours and minutes as expected. However the puzzle part comes when we struggle to get the seconds. We would need to get from latitude the decimal part: 0.1493327E7, and from minutes its decimal part: 0.6700.

However we are getting 0.149332E7 for the latitude and 0.0 for the longitude. The doubt is: how could we get the remaining decimal, and calculate the seconds?

To be able to debug it we have read:

https://www.thoughtco.com/decimal-degrees-conversion-1434592
https://stackoverflow.com/questions/36474338/converting-string-to-double-with-dotç
https://stackoverflow.com/questions/5769669/convert-string-to-double-in-java
https://stackoverflow.com/questions/27480633/converting-from-string-to-double?noredirect=1&lq=1

To sum up, how could we calculate the remaining decimals, after calculating the minutes, to be able to get the seconds?

Yone
  • 2,064
  • 5
  • 25
  • 56

3 Answers3

0

Instead of dealing with strings, first convert the amount of degrees to a whole number of seconds.

double latDegrees = 48.858222;
int latSeconds = (int) Math.round(latDegrees * 60 * 60); // = 175890

Now you can tease out the individual parts with simple integer arithmetic.

int seconds = latSeconds % 60; // = 30
int minutes = (latSeconds / 60) % 60; // = 51
int degrees = (latSeconds / 60) / 60; // = 48

Here's an alternative approach which may be easier to understand if you're not familiar with the modulo operator %:

double latDegreesWithFraction = 48.858222;
int degrees = (int) latDegreesWithFraction; // = 48

double fractionalDegrees = latDegrees - degrees; // = .858222
double minutesWithFraction = 60 * fractionalDegrees; // = 51.49332
int minutes = (int) minutesWithFraction; // = 51

double fractionalMinutes = minutesWithFraction - minutes; // = .49332
double secondsWithFraction = 60 * fractionalMinutes; // = 29.6
int seconds = (int) Math.round(secondsWithFraction); // = 30
Joni
  • 108,737
  • 14
  • 143
  • 193
0

The way you have calculated minutes and seconds is unnecessarily complex. You can make it simpler as follows:

public class Main {
    public static void main(String[] args) {
        String latMinutesStr = "858222";// latSplitted[1]
        double latMinutesFraction = Double.parseDouble("0." + latMinutesStr) * 60;
        int latMinutes = (int) latMinutesFraction;
        System.out.println(latMinutes + " minutes");
        double latSeconds = (latMinutesFraction - latMinutes) * 60;
        System.out.println(String.format("%.2f", latSeconds) + " seconds");
    }
}

Output:

51 minutes
29.60 seconds

In fact, the whole calculation can be made much simpler as follows:

public class Main {
    public static void main(String[] args) {
        String lat = "48.858222";
        double degrees = Double.parseDouble(lat);
        double minutes = (degrees - (int) degrees) * 60;
        double seconds = (minutes - (int) minutes) * 60;
        System.out.println((int) degrees + " degrees " + (int) minutes + " minutes " + String.format("%.2f", seconds)
                + " seconds");
    }
}

Output:

48 degrees 51 minutes 29.60 seconds
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

To do the conversion you basically just get successively remainders of 60.

  • The provide values are lat: 48.858222 lon: 2.2945

  • The hours are simply the int value of the the value or 48

  • The minutes are the fractional part * 60. This works since your take the appropriate fractional part of 60.

    • .858222 * 60 = 51.49332 rounded to and converted to an int or 51.
  • The seconds are the fractional part of minutes * 60 + .5 to round up.

    • .49332 * 60 = 29.59968 +.5 rounded up and converted to to an int or 30

In Java it is convenient to use the % operator to get the remainder or the fractional part of a double or float. Just use 1 as the modulus.

Putting it all together in a lambda which takes the double and returns as string you have.

    static Function<Double, String> HrsMinsSecs = (f) -> f.intValue()
            + " Degrees " + ((int) ((f % 1) * 60)) + " Minutes "
            + ((int) ((((f % 1) * 60) % 1) * 60 + .5)) + " Seconds";

    public static void main(String[] args) {

        double lat = 48.858222;
        double lon = 2.2945;
        System.out.println("Latitude:  " + HrsMinsSecs.apply(lat));
        System.out.println("Longitude: " + HrsMinsSecs.apply(lon));     
    }

This prints

Latitude:  48 Degrees 51 Minutes 30 Seconds
Longitude: 2 Degrees 17 Minutes 40 Seconds

WJS
  • 36,363
  • 4
  • 24
  • 39