2010-08-24 6 views
2

Я только недавно вскочил в мир разработки iphone и цели-c, поэтому я все еще немного потерял, как я могу реализовать что-то подобное.Как сопоставить список диапазонов с одним значением?

У меня есть поплавок, и у меня есть список диапазонов, которые плавают могут подпадать и соответствующее значение, я должен вернуться, например:

10.0 - 14.5 : 1.0 
14.5 - 17.0 : 2.0 
17.0 - 23.0 : 2.5 
23.0 - 32.4 : 4.0 

Так что, если мой поплавок, скажем, 15,12, я хочу вернуть 2.0.

Часть, которая делает эту сложную задачу, состоит в том, что список диапазонов довольно длинный, и у меня есть несколько таких списков диапазонов, которые мне нужно выбрать, любой из которых, возможно, потребуется изменить позже. Просто написать несколько сотен или тысяч слов if выглядит как уродливое решение, если не сказать больше.

ответ

2

По существу, что вы описываете Fuzzy Logic.

Я написал вам правил нечеткой логики класса, который должен обрабатывать то, что вы хотите делать.

Особенности:

  • Вы можете добавить свои собственные правила легко с помощью метода я предоставил.
  • Вы можете проверить значение с помощью одного method и получить строковый результат (или nil, если он не соответствует правилам).
  • Как он использует правила, вы можете определить любые Интервал периодов, которые вы пожелаете.

Добавить новое правило:

[logic addRule:@"2.0" forLowerCondition:14.5 forUpperCondition:17.0]; 

Пример вывода (из кода ниже):

Result for 15.20 is: 2.0 

Вот реализация кода .....

В вашей основной:

FuzzyLogic *logic = [[FuzzyLogic alloc] initWithRule:@"1.0" forLowerCondition:10.0 forUpperCondition:14.5]; 

[logic addRule:@"2.0" forLowerCondition:14.5 forUpperCondition:17.0]; 
[logic addRule:@"2.5" forLowerCondition:17.0 forUpperCondition:23.0]; 

double input1 = 15.2f; 

NSLog(@"Result for %.2lf is: %@", input1, [logic fuzzyResultForValue:input1]); 

[logic release]; 

FuzzyLogic.h:

#import <Foundation/Foundation.h> 

@interface FuzzyLogic : NSObject { 
    NSMutableArray *conditions; 
} 

- (id) initWithRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper; 
- (void) addRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper; 
- (NSString*) fuzzyResultForValue:(double)input; 

@end 

FuzzyLogic.m:

#import "FuzzyLogic.h" 

@implementation FuzzyLogic 

enum { 
    lowerIndex = 0, 
    upperIndex, 
    resultIndex 
}; 

- (id) initWithRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper { 
    self = [super init]; 
    if (self != nil) { 
     [self addRule:result forLowerCondition:lower forUpperCondition:upper]; 
    } 
    return self; 
} 

- (void) addRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper { 

    NSArray *rule = [[NSArray alloc] initWithObjects:[NSString stringWithFormat:@"%lf",lower],[NSString stringWithFormat:@"%lf",upper],result,nil]; 

    if (conditions == nil) { 
     conditions = [[NSMutableArray alloc] initWithObjects:rule,nil]; 
    } else { 
     [conditions addObject:rule]; 
    } 
} 

- (NSString*) fuzzyResultForValue:(double)input 
{ 
    NSString *returnable = nil; 

    // Find the result 
    for (NSArray *cond in conditions) { 
     double lower = [[cond objectAtIndex:lowerIndex] doubleValue]; 
     double upper = [[cond objectAtIndex:upperIndex] doubleValue]; 
     if ((input >= lower && input < upper)) { 
      returnable = [cond objectAtIndex:resultIndex]; 
      break; 
     } 
    } 

    if (returnable == nil) 
    { NSLog(@"Error: Input met no conditions!");} 
    return returnable; 
} 

@end 
3

Если диапазоны все смежные, вы можете создать для них собственный класс коллекций и реализовать его с помощью двух параллельных массивов чисел.

Каждое число в первом массиве один конец одного или двух диапазонов:

  • 10,0
  • 14,5
  • 17,0
  • 23,0
  • 32,4

Второй массив содержит меньшее число; эти цифры значение для отображения на:

  • 1,0
  • 2,0
  • 2,5
  • 4,0

Вашей реализацию поиска в этой коллекции будет состоять из сравнения запрашиваемого номера ключа для каждого число в массиве ключей и номер после него. Было бы проще реализовать линейный поиск, по крайней мере сначала (вы можете оптимизировать его позже с помощью инструментов или акулы). Например, скажите, что этот объект задан около 20:

  • 10,0 ≤ 20 < 14,5? №
  • 14,5 ≤ 20 < 17,0? №
  • 17,0 ≤ 20 < 23,0? Да.

Установив, что запрошенное значение ключа находится в пределах третьего диапазона, вы возвращаете третье значение (2.5).

+0

Нет причин вы не могли. Это деталь реализации; вопросик может реализовать линейный поиск, чтобы заставить его работать (по крайней мере, достаточно долго, чтобы написать единичные тесты, чтобы это доказать), а затем изменить его на секционированный поиск, если инструменты или акула или выбор времени тестов подтверждают, что линейный поиск не достаточно быстрый , –

+0

(Предыдущий комментарий был в ответ на вопрос, почему бы не использовать бинарный поиск вместо линейного.) Я вижу, что этот ответ поднял нижний предел; кто бы это ни объяснил, объясните почему? –

Смежные вопросы