在 c++ 中将角度的正弦值作为双精度
Getting the sine of an angle as a double in c++
对于我的应用程序,由于我得到了由舍入误差引起的错误结果(例如,在地球表面相隔 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))
对于输入数据,lat1
和lat2
非常接近。此外,long2
和long1
之间的差异非常小,因此其余弦将非常接近 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)
接近0
x
。消除后者的精度损失更加困难(但对于给定的输入也不那么重要(。
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 正在将csv文件读取为双精度矢量
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 如何在C++中的同一函数中使用字符串和双精度
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 检查是否以特定精度给出双精度
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- C 字符串返回字符串的整数/双精度/长整型值
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- 如何使双精度值的 C++ 和 C# 中的结果相同
- 使用浮点数和双精度数的非常小数字的数学
- 使用 Xcode 将双精度存储在数组C++中
- 在 C++ 中将双精度变量写入二进制文件
- 如何从字符串转换为双精度*
- 为什么我的数组双精度函数不起作用?
- 高精度双精度的 Sprintf 格式化问题
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 将指针数组分配给双精度
- C++如何将字符串逐行转换为双精度
- 长双精度C++是IEEE二进制128的实现吗?