私は、緯度/経度座標が与えられた地球表面上の 2 点間の距離を計算する、PC 上で実行される Visual C++ で記述された、長年確立されたルーチンを持っています。
これを Android への移植の一環として Java に変換しましたが、結果が異なります。この理由を調査するために、複雑な三角方程式をビットに分割して、各ステップで何が起こっているかを追跡しました。
ただし、Visual C++ では、段階的な計算の結果は、複雑なステートメントから得られた結果とは異なりますが、明らかに同じである必要があります。理由が知りたいです!
予想どおり、Java バージョンは両方のケースで同じ結果をもたらします。
Visual C++ コードは次のとおりです。
double CCoord::GetDistanceRadians(double dLatRadians, double dLongRadians)
{
double dResult;
// This is the step by step code
double r1, r2, r3, r4, r5;
r1 = sin(m_dLatRadians);
r2 = sin(dLatRadians);
r3 = cos(dLatRadians);
r4 = m_dLongRadians - dLongRadians;
r5 = cos(r4);
r1 *= r2;
r2 = r3 * r3;
r2 *= r5;
r4 = r1 + r2;
// This is the original statement: r4 and dResult should be equal
// (but they aren't)
dResult = sin(m_dLatRadians) * sin(dLatRadians) +
cos(m_dLatRadians) * cos(dLatRadians) * cos(m_dLongRadians - dLongRadians);
// Protect against maths processor inaccuracies
if ((dResult > 1.0) || (dResult < -1.0))
dResult = 0.0;
else
dResult = acos(dResult);
return dResult;
}
Javaコードは次のとおりです。
// Return angular distance in radians
private double getDistanceRadians(double dLatRadians, double dLongRadians)
{
double result;
// Do JIT test
checkRadianValues();
// This is the step by step code
double r1, r2, r3, r4, r5;
r1 = Math.sin(m_dLatRadians);
r2 = Math.sin(dLatRadians);
r3 = Math.cos(dLatRadians);
r4 = m_dLongRadians - dLongRadians;
r5 = Math.cos(r4);
r1 *= r2;
r2 = r3 * r3;
r2 *= r5;
r4 = r1 + r2;
// This is the original statement: r4 and result should be equal
// (and they are)
result = Math.sin(m_dLatRadians) * Math.sin(dLatRadians) +
Math.cos(dLatRadians) * Math.cos(dLatRadians) *
Math.cos(m_dLongRadians - dLongRadians);
// Protect against maths processor inaccuracies
if ((result > 1.0d) || (result < -1.0d))
result = 0.0d;
else
result = Math.acos(result);
return result;
}
入力値と結果値は次のとおりです。
Variable VC++ value Java value
m_dLatRadians 0.896808347 0.896808378
m_dLongRadians -0.047414778(0) -0.047414778(6)
dLatRadians 0.896192633(9) 0.896192588(9)
dLongRadians -0.026897463 -0.026897463
r4 1.000218106 1.0002181433
dResult/result 0.999917766 1.0002181433
Visual C++ バージョンで r4 と dResult が異なる理由を誰か教えてください。
PS VC++ バージョンからは良好な最終距離結果が得られ、Java からは悪い最終結果が得られます - ほぼすべての距離がゼロになります (これらのルーチンを呼び出す上位レベルのコードは、たくさんあるため表示されません! ただし、不一致です)について調べることに興味があります)。