2012-04-17 20 views

答えて

55

どちらの任意の構造体タイプの2つのインスタンスを比較するための一般的なアプローチ:

memcmp(&cllc2d1, &second_cllc2d, sizeof(CLLocationCoordinate2D)) 

または

cllc2d1.latitude == cllc2d2.latitude && cllc2d1.longitude == cllc2d2.longitude 

が動作するはずです、あなたは本当に彼らが正確同じだことを確認したい場合。 epsilonは、あなたが受け入れるようにしたいエラーのどんなレベルである

fabs(cllc2d1.latitude - cllc2d2.latitude) <= epsilon && fabs(cllc2d1.longitude - cllc2d2.longitude) <= epsilon 

:しかし、緯度と経度がダブルスのように定義されていることを考えると、あなたは本当に「十分に近い」の比較をしたいかもしれません。

+4

構造体がメンバー間でバイトなしでパックされていると仮定しているため、最初はスケッチと見なされることがあります。 – joerick

+0

良い点。作成/割り当て時に構造体全体をゼロにすると、memcmpのアプローチはパックされていない構造体であっても安全ですが、そうでない場合は慎重に使用してください。 – Glenn

+1

@Glennは、ファブや Shmidt

1
CLLocationCoordinate2D c1, c2; 
if (c1.latitude == c2.latitude && c1.longitude == c2.longitude) 
{ 
    // ... 
} 

私は冗談ではありません。 CLLocationCoordinate2DはC構造体であり、個々のメンバーを比較する以外に、C構造体を比較する簡単な方法はありません。

1

CLLocationCoordinate2Dは、このように、あなたがそのフィールドを比較する必要があり、Cの構造体である:

CLLocationCoordinate2D coord1, coord2; 
if (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude) { 
    // coordinates are equal 
} 

注意、CLLocationCoordinate2Dフィールドは、このように、あなたが他の浮動小数点の比較と同様に同じ問題を得ることができ、doubleです。したがって、私は例えば、少し値を丸めることをお勧め:

CLLocationCoordinate2D coord1, coord2; 
if (round(coord1.latitude * 1000.0) == round(coord2.latitude * 1000.0) 
    && round(coord1.longitude * 1000.0) == round(coord2.longitude * 1000.0)) { 
    // coordinates are equal 
} 

はい、これは、コードが遅いですが、これはあなたが浮動小数点数のように完璧ではない精度に起因する問題を回避するために役立つかもしれません。

32

これらすべての答えに小さな追加として、それはプリプロセッサとして定義された比較が定義持っていることは非常に便利です:

#define CLCOORDINATES_EQUAL(coord1, coord2) (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude) 

またはイプシロンと:

#define CLCOORDINATE_EPSILON 0.005f 
#define CLCOORDINATES_EQUAL2(coord1, coord2) (fabs(coord1.latitude - coord2.latitude) < CLCOORDINATE_EPSILON && fabs(coord1.longitude - coord2.longitude) < CLCOORDINATE_EPSILON) 

これはあなたがすることができます比較は次のようになります。

CLLocationCoordinate2D resultingCoordinate = ... a method call ...; 
CLLocationCoordinate2D expectedCoordinate = CLLocationCoordinate2DMake(48.11, 11.12); 

if(CLCOORDINATES_EQUAL(resultingCoordinate, expectedCoordinate)) { 
    NSLog(@"equal"); 
} else { 
    NSLog(@"not equal"); 
} 

また、インラインメソッドを使用することもできますプリプロセッサとは違います。

+2

浮動小数点数を '=='と比較しないでください。人々が 'イプシロン 'を使う答えを見てください。 – DanSkeel

+0

@DanSkeel私の編集された答えを見てください。場合によっては、正確な座標を比較したいユースケースがあります。例えば。座標のソースが場所データベースであり、それらを比較したい場合のみです。それで、等しい比較のための範囲の必要はありません。だからあなたはもう一度投票を考えているかもしれません。 – Klaas

+1

あなたは私のポイントを得ていません。 '1!= 0.99999999999'の場合を想像してみてください...浮動小数点比較の一般的なルールです。 [について読む](http://floating-point-gui.de/errors/comparison/)それ。このルールはコンピュータとして古いものです。 – DanSkeel

10

CLLocationクラスのdistanceFromLocation:メソッドを使用できます。戻り値はCLLocationDistanceであり、実際は2倍です。

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location 
8

あなたはかなりCoreLocationから来るように感じている機能を定義することができます。

BOOL CLLocationCoordinateEqual(CLLocationCoordinate2D coordinate1, CLLocationCoordinate2D coordinate2) { return (fabs(coordinate1.latitude - coordinate2.latitude) <= DBL_EPSILON && fabs(coordinate1.longitude - coordinate2.longitude) <= DBL_EPSILON); }

+0

これは最も保守的な解決策であるため、これを上書きします。IMO – mvanallen

+0

良い解決策。ここでは、新しいハチのための完全な方法です。 - (BOOL)compairLastSavedCoordinates:(CLLocationCoordinate2D)coordinate1 withNewCoordinates :(CLLocationCoordinate2D)coordinate2 { return(coordinate1.latitude == coordinate2.latitude)&&(coordinate1.longitude == coordinate2.longitude); } – iLearner

+2

浮動小数点数を比較しないでください!あなたがそうした場合、それは信頼できません。実際には、異なるソースから生成された実際の場所からのほとんどの比較は、お互いにかなり近く、「等しい」とみなされても、「偽」を返します。 – CouchDeveloper

1

あなたがこの機能に+ (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinate

を使用してNSValueCLLocationCoordinateをラップそして比較することisEqualToValueを使用することができます。 isEqualToValue関数のアップルドキュメントから

引用:

NSValueクラスは、等価を決定するために各値オブジェクトの種類と内容を比較します。

参考:NSValue

0

のアップルのドキュメント私たちは、NSStringのに緯度と経度を変換してから比較する文字列を行うことができます。

+ (BOOL)isEqualWithCoordinate:(CLLocationCoordinate2D)location1 withAnotherCoordinate:(CLLocationCoordinate2D)location2{ 
NSString *locationString1 = [NSString stringWithFormat:@"%g, %g", location1.latitude, location1.longitude]; 
NSString *locationString2 = [NSString stringWithFormat:@"%g, %g", location2.latitude, location2.longitude]; 

if ([locationString1 isEqualToString:locationString2]) { 
    return YES; 
}else{ 
    return NO; 
} 

}

% gは4桁の10進数を切り捨てる変換するからです。

12

スウィフト拡張子:

import MapKit 

extension CLLocationCoordinate2D: Equatable {} 

public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool { 
    return (lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude) 
} 

[Xcodeの7.3.1、スウィフト2.2のように試験] [そして、もちろん、まだ浮動小数点値を比較する固有の危険性を持っているので、あなたがしたい場合があります以前の回答で述べたようにepsilonを使用することを検討してください]

2

Swift 3では、DBL_EPSILONは推奨されていません。 Double.ulpOfOneを使用してください。

extension CLLocationCoordinate2D { 
    func isEqual(_ coord: CLLocationCoordinate2D) -> Bool { 
     return (fabs(self.latitude - coord.latitude) < .ulpOfOne) && (fabs(self.longitude - coord.longitude) < .ulpOfOne) 
    } 
} 
関連する問題