Search code examples
javapythonlatitude-longitude

Unique Number generation based on latitude and longitude in Java and Python


I am trying to implement unique number generation based on latitude and longitude such that for same latitude and longitude pair the number generated should be same.

Other than that generated number should not exceed the maximum value of Integer in Java, which is 2147483647

Following python function is working fine

def get_unique_number(lat, lon):
  try:
    lat_double = None
    lon_double = None
    if isinstance(lat, str):
        lat_double = float(lat)
    else:
        lat_double = lat
    if isinstance(lon, str):
        lon_double = float(lon)
    else:
        lon_double = lon

    lat_int = int((lat_double * 1e7))
    lon_int = int((lon_double * 1e7))
    val = abs(lat_int << 16 & 0xffff0000 | lon_int & 0x0000ffff)
    val = val % 2147483647
    return val
except Exception as e:
    print("marking OD_LOC_ID as -1 getting exception inside get_unique_number function")
    print("Exception while generating od loc id")
    print(traceback.format_exc())
    return None

I need an equivalent Java implementation.

I have come up with a Java implementation of above function but that is not working for some of the latitude/longitude pair

public static int getUniqueId(double lat,double lon) {
    int lat_int = (int) (lat * 10000000);
    int lon_int = (int) (lon *  10000000);
    int val=Math.abs(lat_int << 16 & 0xffff0000 | lon_int & 0x0000ffff);
    val = val % Integer.MAX_VALUE;
    System.out.println(val);
    return val;
}

Some of the latitude/longitude pairs for which the two implementations are not returning same results are

  1. 44.6212179,-75.6963195
  2. 40.2318791,-78.9155315

How can I get same results from both python and Java implementation. It would really help if the implementation for Java is corrected as python implementation is working in Production environment.


Solution

  • Possibly, you should be using long type for Java implementation (because Python int is not as limited by length as its Java counterparts):

    public static long getUniqueId(double lat,double lon) {
        long lat_int = (long) (lat * 10000000);
        long lon_int = (long) (lon * 10000000);
        long latMask = lat_int > 0x7FFF0000L ? 0x1ffff0000L : 0xffff0000L;
        long val=Math.abs(lat_int << 16 &  latMask | lon_int & 0x0000ffff);
        val = val % Integer.MAX_VALUE;
        System.out.println(val);
        return val;
    }
    

    Then for the given inputs the outputs will be:

    44.6212179,-75.6963195 -> OLD: 676584886  -> 676571270
    40.2318791,-78.9155315 -> OLD: 1707581954 -> 1707569678
    

    Update Fixed the constant to allow one extra bit in the mask 0x1ffff0000L

    Tested with additional data close to max/min limits of latitude and longitude -- the results are the same as for Python code.

    getUniqueId( 179.8213878,  179.6963195);  // 284588923
    getUniqueId( 179.8213878, -179.6963195);  // 284591239
    getUniqueId(-179.6963195,  179.8213878);  //  75927799
    getUniqueId(-179.6963195, -179.8213878);  //  75919115
    

    Update 2

    For the example in comments (44.6212179,-75.696319):

    New example: (44.3252130,-79.6794917)