2

Here I am having a query about how double works with their precision.

I created a sample where in I entered the double values as below:

double d = 2.0126161;
double d1 = 2.0126162;
double d2 = 2.0126163;
double d3 = 2.0126164;
double d4 = 2.0126165;

Current Output:

If I put break point and check by running "po" command in lldb then values show up as below:

(lldb) po d
2.0126160999999998

(lldb) po d1
2.0126162000000001

(lldb) po d2
2.0126162999999999

(lldb) po d3
2.0126164000000002

(lldb) po d4
2.0126165

I am assigning these doubles to CLLocation object's latitude and longitude which have a datatype "double".

Here as you can see the output, shows that the “po” command for d4 prints the value “2.0126165” which is same as the value which we gave explicitly to d4 which is perfectly fine and what I want.

Issue:

But “po” commands for d, d1, d2, d3 have changes in the value as compared to what we explicitly passed.

This changes in value of d, d1, d2, d3 creates a difference in the calculation we do involving double d, d1, d2, d3. And if we check the cumulative effect shows that there are significant differences compared to the output we expect.

I don't want to round off the value to specific number of decimal places as that varies from value to value.

How can I have d, d1, d2, d3 to have same values as they were explicitly initialized with and not change the precision using datatype double (Check the expected output below)?

Expected Output:

(lldb) po d
2.0126161

(lldb) po d1
2.0126162

(lldb) po d2
2.0126163

(lldb) po d3
2.0126164

(lldb) po d4
2.0126165

Note: Please take a note of it that I don't want to display this value on screen, I am using these double values for mathematical calculations, so no point converting to NSString by passing "%.7f" as a format specifier for NSString.

Parth Bhatt
  • 19,381
  • 28
  • 133
  • 216
  • How significant are the differences? Assuming double is IEEE 754 64-bit binary floating point, on a simple conversion the rounding error will be no more than one part in 2^53. In the context of latitude and longitude, the basic rounding error will be about one ten millionth of an inch. Are you sure you cannot tolerate the differences, and round only for display? – Patricia Shanahan Apr 21 '15 at 06:53
  • @PatriciaShanahan: Yes, cumulative effect of this calculations leads us to a point where in we find some significant difference in the projections of points on the map. – Parth Bhatt Apr 21 '15 at 07:00
  • Which is more accurate, the calculation to a limited number of decimal places or the double calculation? – Patricia Shanahan Apr 21 '15 at 07:52
  • @PatriciaShanahan: The calculation to a limited number of decimal places gives me more accurate results in my case. – Parth Bhatt Apr 21 '15 at 09:12

2 Answers2

1

What you experience is normal, there is an indefinite amount of numbers which has to be mapped to a definite amount of bytes. So often you will not get the exact number you entered, but the next closest that can be represented in the chosen number format.

For mathematical calculations use NSDecimalNumber.

Volker
  • 4,640
  • 1
  • 23
  • 31
  • Thanks for your response. How can I use NSDecimalNumber? Also the thing is that I use CLLocation objects which have latitudes and longitudes as double. I involve CLLocation objects for many calculations. – Parth Bhatt Apr 21 '15 at 06:06
  • You can create the NSDecimalNumbers from the latitudes/longitudes you have. Does the "inprecision" of double you reported do any harm to your lat/long calculations? – Volker Apr 21 '15 at 06:09
  • Also problem in using NSDecimalNumber is that, when assigning these values to CLLocation's latitude and longitude, we would have again change it to double value using something like `double latitude = [objDecimalNumber doubleValue];`. So issue again remains the same. – Parth Bhatt Apr 21 '15 at 06:25
  • Consider about what you are thinking - the issue must exist in first place since CLLocations use doubles. So either keep the doubles and accept the precision they have or switch to NSDecimalNumber. From your question it wasn't clear where the data comes from and where it is used. So it might be okay to go with double precision all the time and the errors may only be marginally. – Volker Apr 21 '15 at 06:33
  • Yes, you are right about the question. The question was not clear on where we assign and derives these double values from. I have edited the question. Thanks. – Parth Bhatt Apr 21 '15 at 06:44
  • Okay, then you cannot solve it since CLLocation finally works with doubles. Have you checked the actual difference ein meters between the values you supply and the one stored in the doubles? – Volker Apr 21 '15 at 07:01
  • Yes, actually when I push a CLLocation and project a point on the map, there is a some significant difference on the original point and projected point on map. The same works fine in Android. – Parth Bhatt Apr 21 '15 at 07:43
0

You are using CLLocation which has double type attributes (Latitude and Longitude).

double type is using 16 digit after decimal point by default. To get the exact value you assign, do like this:

double d = 2.0126161000000000; 

For the remaining digits, use 0s and adjust the length to 16.

Hope this will help.

Mrunal
  • 13,982
  • 6
  • 52
  • 96