NSArray
に含まNSNumbers
れるすべての値を比較しfloats
て最大のものと最小のものを見つける効果的で優れた方法は何ですか?
Objective-Cでこれをすばやくすばやく行う方法はありますか?
NSArray
に含まNSNumbers
れるすべての値を比較しfloats
て最大のものと最小のものを見つける効果的で優れた方法は何ですか?
Objective-Cでこれをすばやくすばやく行う方法はありますか?
実行速度(プログラミング速度ではなく) が重要な場合は、明示的なループが最も高速です。1000000 個の乱数の配列を使用して、次のテストを行いました。
バージョン 1: 配列を並べ替える:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:@selector(compare:)];
// 1.585 seconds
バージョン 2: 「doubleValue」を使用したキー値コーディング:
NSNumber *max=[numbers valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:@"@min.doubleValue"];
// 0.778 seconds
バージョン 3: 「self」を使用したキー値コーディング:
NSNumber *max=[numbers valueForKeyPath:@"@max.self"];
NSNumber *min=[numbers valueForKeyPath:@"@min.self"];
// 0.390 seconds
バージョン 4: 明示的なループ:
float xmax = -MAXFLOAT;
float xmin = MAXFLOAT;
for (NSNumber *num in numbers) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
// 0.019 seconds
バージョン 5: ブロック列挙:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
[numbers enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}];
// 0.024 seconds
テスト プログラムは、1000000 個の乱数の配列を作成し、すべての並べ替え手法を同じ配列に適用します。上記のタイミングは 1 回の実行の出力ですが、約 20 回実行し、各実行で非常に類似した結果が得られます。また、キャッシュ効果を除外するために、5 つの並べ替え方法が適用される順序を変更しました。
更新: (できれば) より優れたテスト プログラムを作成しました。完全なソース コードはhttps://gist.github.com/anonymous/5356982にあります。1000000 個の乱数の配列をソートする平均時間は次のとおりです (秒単位、3.1 GHz Core i5 iMac、リリース コンパイル)。
並べ替え 1.404 KVO1 1.087 KVO2 0.367 高速列挙 0.017 ブロック列挙 0.021
更新 2:ご覧のとおり、高速列挙はブロック列挙よりも高速です (これは、http: //blog.bignerdranch.com/2337-incremental-arrayification/にも記載されています)。
編集:以下は完全に間違っています。Hot Licks が正しく認識したように、ロックとして使用されるオブジェクトを初期化するのを忘れたため、同期がまったく行われないためです。またlock = [[NSObject alloc] init];
、同時列挙は非常に遅いため
、あえて結果を表示しません。おそらく、より高速な同期メカニズムが役立つかもしれません...)
NSEnumerationConcurrent
オプションをブロック列挙に
追加すると、これは劇的に変化します。
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
id lock;
[numbers enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
@synchronized(lock) {
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
}];
ここでのタイミングは
同時列挙型 0.009
したがって、高速列挙の約 2 倍の速さです。結果は、使用可能なスレッドの数に依存するため、おそらく代表的なものではありません。でもとにかく面白い!「最も使いやすい」同期方法を使用したことに注意してください。これは、最速ではない可能性があります。
NSNumber の下にラップして float を保存し、次に
NSNumber *max=[numberArray valueForKeyPath:@"@max.doubleValue"];
NSNumber *min=[numberArray valueForKeyPath:@"@min.doubleValue"];
*コンパイルおよびチェックされていない、intValue でチェック済み、double か float か不明
それを並べ替えます。最初と最後の要素を取ります。
ところで:フロートを NSArray に格納することはできません。それらを NSNumber オブジェクトでラップする必要があります。
NSArray *numbers = @[@2.1, @8.1, @5.0, @.3];
numbers = [numbers sortedArrayUsingSelector:@selector(compare:)];
float min = [numbers[0] floatValue];
float max = [[numbers lastObject] floatValue];