有没有更好的方法来确定两个枚举值之间的距离?

时间:2014-05-05 23:36:30

标签: ios c enums

我有一个8位移位值的枚举。我希望能够确定任何两个值之间的距离。如果值只是增加整数,这将很简单。这就是我现在所拥有的。

typedef NS_ENUM(NSInteger, TestEnum) {
    TestEnumValue1 = 1 << 0,
    ...
    TestEnumValue8 = 1 << 7
};

TestEnum left = TestEnumValue8;
TestEnum right = TestEnumValue3;

TestEnum high = MAX(left, right);
TestEnum low = MIN(left, right);

int distance = 0;
int maximumEnum = 8;
int cumulativeResult = high;
for (int i = 0; i < maximumEnum; i++) 
{
    cumulativeResult = cumulativeResult / 2;
    if (cumulativeResult == low)
    {
        distance = i;
        break;
    }
}
NSLog (@"Distance is %d", distance);

以上似乎运作良好,但这是最好的方法吗?

3 个答案:

答案 0 :(得分:2)

忽略使用枚举是否合适,请尝试:

TestEnum left = TestEnumValue8;
TestEnum right = TestEnumValue3;

TestEnum high = MAX(left, right);
TestEnum low = MIN(left, right);

int distance = 0;
while (low < high) {
    low <<= 1;
    distance++;
}

NSLog (@"Distance is %d", distance);

请注意,仅当leftright设置了一个“标记”时,此方法才有效。

答案 1 :(得分:1)

这是一个潜在的解决方案:添加两个(正)整数并计算一位之间的零位。加法的可交换性消除了确定哪个操作数更大的繁琐需求。

int distance;
int k = left + right;
int started = 0;
while (k > 1) {
        if (!started && (k & 1)) {
                started = 1;
                distance = 0;
        }
        if (started) distance++;
        k >>= 1;
}

printf("%d\n", distance);

答案 2 :(得分:1)

我把一些令人讨厌的东西混在一起,但是哪种工作方式允许使用枚举值,这些值不是连续的2次幂。 以下是&#39; enum&#39;定义,实际的枚举值在DEFINE_MYENUM(x,y)语句中定义:

#include <cmath>
#include <map>

class Value {
public:
    virtual operator int() const = 0;
    int getIndex() const { return index; }

    static const Value& fromValue(int val)
    {
        return *(getReverseMap().find(val)->second);
    }

protected:
    int index;
    static int getNextIndex() {
        static int curIndex = 0;
        return curIndex++;
    }
    static std::map<int, Value*>& getReverseMap() {
        static std::map<int, Value*> reverseMap = std::map<int, Value*>();
        return reverseMap;
    }
};

template<int y> class ValueImpl : Value {
public:
    ValueImpl() {
        index = Value::getNextIndex();
        Value::getReverseMap()[y] = this;
    }
    virtual operator int() const override { return y; }
};

#define DEFINE_MYENUM(NAME, VALUE) const ValueImpl<VALUE> NAME
class MyEnumDefs {
public:
    DEFINE_MYENUM(Value1, 2);
    DEFINE_MYENUM(Value2, 4);
    DEFINE_MYENUM(Value3, 8);
    DEFINE_MYENUM(Value4, 16);
    DEFINE_MYENUM(Value5, 20);
    DEFINE_MYENUM(Value6, 25);

    int distance(const Value& x, const Value& y) {
        return std::abs(x.getIndex() - y.getIndex());
    }
    int distance(int x, int y) {
        const Value& xx = Value::fromValue(x);
        const Value& yy = Value::fromValue(y);
        return distance(xx, yy);
    }
};
#undef DEFINE_MYENUM

class MyEnum {
public:
    static MyEnumDefs& inst() {
        static MyEnumDefs internalInst = MyEnumDefs();
        return internalInst;
    }
};
#define MyEnum MyEnum::inst()

以下是测试代码:

int main(int argc, const char * argv[])
{
    int a = MyEnum.Value1;
    int b = MyEnum.Value2;
    int c = MyEnum.Value3;
    int d = MyEnum.Value4;
    int e = MyEnum.Value5;
    int f = MyEnum.Value6;
    printf("a b c d e f: %d %d %d %d %d %d\n", a, b, c, d, e, f);

    printf("Distance b d: %d\n", MyEnum.distance(b, d));
    printf("Distance d b: %d\n", MyEnum.distance(d, b));

    printf("Distance e f: %d\n", MyEnum.distance(e, f));
    return 0;
}

输出:

a b c d e f: 2 4 8 16 20 25
Distance b d: 2
Distance d b: 2
Distance e f: 1

显然这并不完美,例如语法MyEnum.XXX而不是XXX或MyEnum :: XXX,缺乏使用&#39; MyEnum&#39;作为一种类型等...但认为它是一个很好的开始可能是非常整洁:)