posted 8 years ago

hi...

when i divide any integer say (126812) when i divide this int with 3600 i get 35.22555555555556 now i again multiply it to 3600 but i don't get exact 126812 in return i get some double in points like 126812.00000001 but i need exact value in return caz i m using that value as key in key value pair for a map. please help me how can i get the exact value..and i have hell lots of values like dis

when i divide any integer say (126812) when i divide this int with 3600 i get 35.22555555555556 now i again multiply it to 3600 but i don't get exact 126812 in return i get some double in points like 126812.00000001 but i need exact value in return caz i m using that value as key in key value pair for a map. please help me how can i get the exact value..and i have hell lots of values like dis

posted 8 years ago

Hi Mukesh,

Some floating point operations require more precision than is available in the system. The result is approximated to fit the available precision. When that result is reused in the inverse operation, you won't get back the original value because of this approximation. This happens in our own calculations too: For example,

7/3 = 2.3333333333 (recurring).

If you multiply this result with 3, you won't get 7, you'll get 6.9999999999 (recurring) which is not quite 7.

One solution would be use Math.round() to get the integer (or long) closest to the double, and use that as the key.

But have you thought through the approach of making a multiplication result as a key? Normally, keys should be unique. But other multiplications may also result in the same key inadvertently replacing a value.

Cheers

Karthik

Some floating point operations require more precision than is available in the system. The result is approximated to fit the available precision. When that result is reused in the inverse operation, you won't get back the original value because of this approximation. This happens in our own calculations too: For example,

7/3 = 2.3333333333 (recurring).

If you multiply this result with 3, you won't get 7, you'll get 6.9999999999 (recurring) which is not quite 7.

One solution would be use Math.round() to get the integer (or long) closest to the double, and use that as the key.

But have you thought through the approach of making a multiplication result as a key? Normally, keys should be unique. But other multiplications may also result in the same key inadvertently replacing a value.

Cheers

Karthik

posted 8 years ago

Please read up on the inaccuracies that are inherent within any floating point type of number:

floating point

The solution: never use a floating point number as a key.

mukesh pandey wrote:hi...

when i divide any integer say (126812) when i divide this int with 3600 i get 35.22555555555556 now i again multiply it to 3600 but i don't get exact 126812 in return i get some double in points like 126812.00000001 but i need exact value in return caz i m using that value as key in key value pair for a map. please help me how can i get the exact value..and i have **** lots of values like dis

Please read up on the inaccuracies that are inherent within any floating point type of number:

floating point

The solution: never use a floating point number as a key.

mukesh pandey

Greenhorn

Posts: 22

posted 8 years ago

hi I agree that i should not use floating kind of number as map but its my requirement, what I am doing is i am mapping a location with the latitude and longitude. latitude and longitude can be float, so here lat and long are key and the location of that area is value. that y i need to use this kind of number as key to key value map

mukesh pandey

Greenhorn

Posts: 22

posted 8 years ago

Round adds .5 and then truncates. 8.1 + 0.5 = 8.6 -> 8, but 8.6 + 0.5 = 9.1 -> 9 so round rounds to the closest integer.

Actually x.5 is half way between x and x.1, so it is equally close to x and x+1. Every floating point implementation that I have ever seen has x.5 round to x+1. That way, exactly half of the bit patterns for the y part of x.y round to x and half round to x+1.

This description only applies to floating point numbers that actually have the integer and fractional parts. For example, 12345678901234567890.6 has no information about the .6 when in float format.

Actually x.5 is half way between x and x.1, so it is equally close to x and x+1. Every floating point implementation that I have ever seen has x.5 round to x+1. That way, exactly half of the bit patterns for the y part of x.y round to x and half round to x+1.

This description only applies to floating point numbers that actually have the integer and fractional parts. For example, 12345678901234567890.6 has no information about the .6 when in float format.

posted 8 years ago

Hi Mukesh,

Since the values in question are latitude/longitude values, I feel you can take an approach like this: Lat/lng values have a set precision (for example, a precision upto 6th decimal place represents around 10 centimeters). Now it's unlikely you'll have more than 1 location within 10 cm. So multiple your floating values by 10^6, round to int/long and use them as keys (maybe combine them into a simple class). Use both rounded values to create a fairly unique hashCode for each combination. As Artem said, you can in fact also use BigDecimal with 6 point precision, instead of rounding to int/long.

For lookups, take the values returned by the mapping platform, use only upto 6 decimal points (using BigDecimal) and then do the lookup. As long as all BigDecimals are used with same precision, you can get exact matches without requiring some kind of tolerance calculation.

Cheers

Karthik

Since the values in question are latitude/longitude values, I feel you can take an approach like this: Lat/lng values have a set precision (for example, a precision upto 6th decimal place represents around 10 centimeters). Now it's unlikely you'll have more than 1 location within 10 cm. So multiple your floating values by 10^6, round to int/long and use them as keys (maybe combine them into a simple class). Use both rounded values to create a fairly unique hashCode for each combination. As Artem said, you can in fact also use BigDecimal with 6 point precision, instead of rounding to int/long.

For lookups, take the values returned by the mapping platform, use only upto 6 decimal points (using BigDecimal) and then do the lookup. As long as all BigDecimals are used with same precision, you can get exact matches without requiring some kind of tolerance calculation.

Cheers

Karthik

It is sorta covered in the JavaRanch Style Guide. |