Oğuzhan KURNUÇ 's answer의 정밀도를 사용 / 증명하는 코드 .
요약 :
작은 크기 (4B)에서 높은 정밀도 (~ 1cm).
[-180, 180] 범위의 값에 대한 정밀도 는 소수점 이하 7 자리입니다.
그건 소수점의 오른쪽의 숫자 7 (~ 1cm) , 9 자리의 총 (또는 10 진수 "180"의 "1"은 초기 수를 계산하는 경우) + -180 가까이 대.
이것을 ~ 7 자리 만 가진 4 바이트 float와 대조하여, + = 180 (~ 1m) 근처에서 소수점 오른쪽 ~ 5 자리 .
이 방법을 사용하는 방법 :
const double Fixed7Mult = 10000000;
public static int DecimalDegreesToFixed7(double degrees)
{
return RoundToInt(degrees * Fixed7Mult);
}
public static double Fixed7ToDecimalDegrees(int fixed7)
{
return fixed7 / (double)Fixed7Mult;
}
정밀도 테스트 :
/// <summary>
/// This test barely fails in 7th digit to right of decimal point (0.0000001 as delta).
/// Passes with 0.0000002 as delta.
/// </summary>
internal static void TEST2A_LatLongPrecision()
{
//VERY_SLOW_TEST Test2A_ForRange(-180, 360, 0.0000001);
//FAILS Test2A_ForRange(-180, 0.1, 0.0000001);
Test2A_ForRange(-180, 0.1, 0.0000002);
Test2A_ForRange(0, 0.1, 0.0000002);
Test2A_ForRange(179.9, 0.1, 0.0000002);
}
/// <summary>
/// Test for the smallest difference. A: 9.9999994E-08.
/// </summary>
internal static void TEST2B_LatLongPrecision()
{
double minDelta = double.MaxValue;
double vAtMinDelta = 0;
//VERY_SLOW_TEST Test2B_ForRange(-180, 360, ref minDelta, ref vAtMinDelta);
Test2B_ForRange(-180, 0.1, ref minDelta, ref vAtMinDelta);
Test2B_ForRange(0, 0.1, ref minDelta, ref vAtMinDelta);
Test2B_ForRange(179.9, 0.1, ref minDelta, ref vAtMinDelta);
// Fails. Smallest delta is 9.9999994E-08; due to slight rounding error in 7th decimal digit.
//if (minDelta < 0.0000001)
// throw new InvalidProgramException($"Fixed7 has less than 7 decimal digits near {vAtMinDelta}");
// Passes.
if (minDelta < 0.000000099)
throw new InvalidProgramException($"Fixed7 has less than 7 decimal digits near {vAtMinDelta}");
}
테스트에 사용되는 도우미 메소드 :
private static void Test2A_ForRange(double minV, double range, double deltaV)
{
double prevV = 0;
int prevFixed7 = 0;
bool firstTime = true;
double maxV = minV + range;
for (double v = minV; v <= maxV; v += deltaV) {
int fixed7 = DecimalDegreesToFixed7(v);
if (firstTime)
firstTime = false;
else {
// Check for failure to distinguish two values that differ only in 7th decimal digit.
// Fails.
if (fixed7 == prevFixed7)
throw new InvalidProgramException($"Fixed7 doesn't distinguish between {prevV} and {v}");
}
prevV = v;
prevFixed7 = fixed7;
}
}
private static void Test2B_ForRange(double minV, double range, ref double minDelta, ref double vAtMinDelta)
{
int minFixed7 = DecimalDegreesToFixed7(minV);
int maxFixed7 = DecimalDegreesToFixed7(minV + range);
bool firstTime = true;
double prevV = 0; // Initial value is ignored.
for (int fixed7 = minFixed7; fixed7 < maxFixed7; fixed7++) {
double v = Fixed7ToDecimalDegrees(fixed7);
if (firstTime)
firstTime = false;
else {
double delta = Math.Abs(v - prevV);
if (delta < minDelta) {
minDelta = delta;
vAtMinDelta = v;
}
}
prevV = v;
}
}