Wil*_*iam 8 c math floating-point modulo intervals
我有代表纬度和经度的双打.
我可以使用以下功能轻松地将经度限制在(-180.0,180.0).
double limitLon(double lon)
{
return fmod(lon - 180.0, 360.0) + 180.0;
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为一端是独占的,另一端是包容性的.fmod包括0但不包括-360.0.
任何人都可以想到一个优雅的纬度方法吗?
所需间隔为[-90.0,90.0].封闭形式的解决方案是最好的,即没有循环.我认为fmod()可能不是首发,因为现在两端都是包容性的.
编辑:正如所指出的那样,无论如何都不能进入91度纬度.技术上91应该映射到89.0.哦,男孩,这会改变一切.
除了使用sin和arcsin之外,还有一种更有效的方法.最昂贵的操作是单一部门.关闭所需间隔的观察结果是关键.
除以360并取余数.[0, 360)如所观察到的,这产生了间隔中的数字,其是半开的.
将间隔折成两半.如果余数> = 180,则将其从360减去.这将间隔映射[180, 360)到间隔(0, 180].该间隔与下半部分的并集是闭合间隔[0, 180].
从结果中减去90.[-90, 90]根据需要,该间隔是.
实际上,这与功能完全相同arcsin(sin(x)),但没有费用或任何数值稳定性问题.
使用trig函数的sin()/cos()时间成本很高,并且会导致精度损失。使用该remainder()功能更好。请注意,结果x与的幅度相同,并且幅度小于的幅度(y如果可以)。
OP走在正确的轨道上!下面的解决方案易于根据-180和+ 180.0的边值进行调整。
#include <math.h>
// Reduce to (-180.0, 180.0]
double Limit_Longitude(double longitude_degrees) {
// A good implementation of `fmod()` will introduce _no_ loss of precision.
// -360.0 <= longitude_reduced <=- 360.0
double longitude_reduced = fmod(longitude_degrees, 360.0);
if (longitude_reduced > 180.0) {
longitude_reduced -= 360.0;
} else if (longitude_reduced <= -180.0) {
longitude_reduced += 360.0;
}
return longitude_reduced;
}
Run Code Online (Sandbox Code Playgroud)
将纬度限制为[-90至+90]比较棘手,因为+91度的纬度将越过北极,但将经度切换+/- 180度。要保持经度精度,请将0向180度调整。
void Limit_Latitude_Longitude(double *latitude_degrees, double *longitude_degrees) {
*latitude_degrees = Limit_Longitude(*latitude_degrees);
int flip = 0;
if (*latitude_degrees > 90.0) {
*latitude_degrees = 180.0 - *latitude_degrees;
flip = 1;
} else if (*latitude_degrees < -90.0) {
*latitude_degrees = -180.0 - *latitude_degrees;
flip = 1;
}
if (flip) {
*longitude_degrees += *longitude_degrees > 0 ? -180.0 : 180.0;
}
*longitude_degrees = Limit_Longitude(*longitude_degrees);
}
Run Code Online (Sandbox Code Playgroud)
次要:尽管目标是“将经度限制为(-180.0,180.0]”,但我希望更普遍地需要[-180.0,180.0),[-180.0,180.0]范围。
使用 和 反函数怎么样sin?
asin(sin((lat/180.0)*3.14159265)) * (180.0/3.14159265);
Run Code Online (Sandbox Code Playgroud)