Как я могу сопоставить список диапазонов одному значению? - PullRequest
2 голосов
/ 24 августа 2010

Я только недавно прыгнул в мир разработки для iphone и target-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

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

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

Ответы [ 2 ]

3 голосов
/ 24 августа 2010

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

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

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

Второй массив содержит на одно число меньше; эти числа являются значениями для сопоставления:

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

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

  • 10,0 ≤ 20 <14,5? Нет. </li>
  • 14,5 ≤ 20 <17,0? Нет. </li>
  • 17,0 ≤ 20 <23,0? Да. </li>

Обнаружив, что запрошенное значение ключа находится в третьем диапазоне, вы возвращаете третье значение (2.5).

2 голосов
/ 24 августа 2010

По сути, вы описываете Нечеткая логика .

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

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

  • Вы можете легко добавлять свои собственные правила с помощью предоставленного мною метода.
  • Вы можете проверить значение с помощью одного 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
...