You need not do this in double precision: single precision is enough! The trouble is what you're using the precision for, and by trying to represent cosines near 1 rather than near 0 you're throwing away all the precision available to you. Navigators in days of yoreβwith much less precision than modern IEEE 754 binary32 single precision!βhad the same problem, and what did they do?
Let's write this as a formula without all the unit conversionsβyou have latitudes πβ and πβ and longitudes πβ and πβ and you want the great-circle angle π, which you've decided to approach with the relation (probably derived from converting the spherical law of cosines naively to a longitude/latitude coordinate system):
cos π = sin πβ sin πβ + cos πβ cos πβ cos(πβ β πβ).
The crux of the problem is that you're trying to find an angle whose cosine is very close to 1, and you're doing it by computing that cosine. In your example, sin πβ sin πβ + cos πβ cos πβ cos(πβ β πβ) comes out to roughly 0.999999937 = 1 β 6.3Γ10β»βΈ, but the single-precision floating-point numbers in [Β½, 1] can only discern increments of about 6Γ10β»βΈ, so you've essentially wasted all your precision on those leading nines. Navigators in days of yore didn't even have eight digits (for example, the 1913 tables of E.R. Hedrick and the 1800 tables of Josef de Mendoza y RΓos provide only around five digits), so how did they do it?
You probably grew up on the three trig functions sine, cosine, and tangent if you're much less than a century old, but there are others like haversine (hav π = Β½ (1 β cos π)) and exsecant (exsec π = sec π β 1 = 1/cos π β 1)βinvented not to torture students in school, but because they made calculations feasible with limited precision! The trick is not to compute the cosine 1 β πΏ for very small πΏ, but instead compute the versine πΏ, or the haversine Β½πΏ, so you can use the full precision available to you to represent it.
The venerable haversine formula relates the latitudes πβ and πβ and longitudes πβ and πβ to the great-circle angle π by:
hav π = hav(πβ β πβ) + cos πβ cos πβ hav(πβ β πβ).
This is better for nearby angles because for small angle differences, haversine preserves most of the precision of the input to return a result near 0, while cosine throws it away to return a result near 1.
Of course, the Android math library might be missing a haversine function (pity!), but you can recover it from the trigonometric identity:
hav π = Β½ (1 β cos π) = sinΒ²(π/2).
You can always divide by two exactly in floating-point arithmetic (unless it underflows), and squaring won't amplify the error much, so the formula sinΒ²(π/2) will work reliably, and you can recover the inverse archav π₯ = 2 arcsin(βπ₯), using functions that probably are in the Android math library. And this identityβtogether with coordinate transformation between longitude/latitude and spherical triangle anglesβis how you can derive the haversine formula from (e.g.) the spherical law of cosines, as the Wikipedia article shows.
Once you use the haversine formula, even if you compute everything in single precision, you get within about 30cm of the exact result in your example, or <0.014% relative errorβwhich is smaller than the error of about 60cm arising from using a spherical approximation to the oblate spheroid of Earth!