在 c++ 中将角度的正弦值作为双精度

Getting the sine of an angle as a double in c++

本文关键字:双精度 c++      更新时间:2023-10-16

对于我的应用程序,由于我得到了由舍入误差引起的错误结果(例如,在地球表面相隔 1853m 的两个点之间计算的距离为 0!(,我需要以双精度计算正弦和余弦。不幸的是,我在 NDK 中找不到任何合适的功能。

如何获得更准确的结果?

我使用的公式是60*1852*toDegrees(acos(sin(toRadians(lat1))*sin(toRadians(lat2))+cos(toRadians(lat1))*cos(toRadians(lat2))*cos(toRadians(long2-long1))))

lat1=45.7729721; lat2=45.792984; long1=2.96383333; long2=2.96895313

通过尝试获得更高的精度来解决这个问题对我来说似乎是一个坏主意。你的问题是可怕的条件,对浮点数不是很好处理。

让我们看一下重要的表达式(省略转换(:

acos(sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(long2-long1))

对于输入数据,lat1lat2非常接近。此外,long2long1之间的差异非常小,因此其余弦将非常接近 1。

鉴于此,acos内的表达式几乎正是这个恒等式:

sin(x)*sin(x) + cos(x)*cos(x) = 1

希望从这个表达式中获取acos将产生你观察到的结果,因为浮点数不会很好地处理这个问题(你在零附近有很多精度,但在其他整数周围没有(。

您应该完全使用不同的公式。我对我聪明的三角恒等式有点生疏,但是如果你手头有你从中得出的几何形状,那么获得一个不同的定义应该不难,它涉及1附近精度的灾难性损失较小。


好的,用 https://en.wikipedia.org/wiki/List_of_trigonometric_identities 武装起来,考虑一下:

sin(lat1)*sin(lat2) = 0.5 (cos(lat1 - lat2) - cos(lat1 + lat2)) =: a
cos(lat1)*cos(lat2) = 0.5 (cos(lat1 - lat2) + cos(lat1 + lat2)) =: b
cos(long2-long1) =: c

然后表达式变为acos(a + b * c),或

0.5 (1 + c) cos(lat1 - lat2) - 0.5 (1 - c) cos(lat1 + lat2)

这里危险取消的条款是(1-c)cos(lat1 - lat2)(至少对于您给定的输入(。对于前者,您可以尝试寻找多项式近似值,以准确计算1 - cos(x)接近0x。消除后者的精度损失更加困难(但对于给定的输入也不那么重要(。