将常量双精度映射到整数的现代C ++方法

时间:2015-10-12 13:56:08

标签: c++ c++11 dictionary

将常量值双精度映射到整数的现代方法是什么?

我希望这只作为标题包含。

我已经避免#define并开始使用if语句的嵌套。

我相信if语句更快(我将它们列为优先级,并且其中有一些goto)但下面的开关似乎更具可读性。

我看了下面的代码拆解,看起来很合理。

我不喜欢巨型开关。我认为可能有更好的现代方法(不会失去性能或需要链接)。

inline int InchtoGauge(double d)
{
    switch (static_cast<int>(d * 10000))
    {
    case 2391: return 3;
    case 2242: return 4;
    case 2092: return 5;
    case 1943: return 6;
    case 1793: return 7;
    case 1644: return 8;
    case 1495: return 9;
    case 1345: return 10;
    case 1196: return 11;
    case 1046: return 12;
    case 897: return 13;
    case 747: return 14;
    case 673: return 15;
    case 598: return 16;
    case 538: return 17;
    case 478: return 18;
    case 418: return 19;
    case 359: return 20;
    case 329: return 21;
    case 299: return 22;
    case 269: return 23;
    case 239: return 24;
    case 209: return 25;
    case 179: return 26;
    case 164: return 27;
    case 149: return 28;
    case 135: return 29;
    case 120: return 30;
    case 105: return 31;
    case 97: return 32;
    case 90: return 33;
    case 82: return 34;
    case 75: return 35;
    case 67: return 36;
    default:return -1;
    }

}

3 个答案:

答案 0 :(得分:2)

执行某些内容的标题实现,认为是一个问题,这不是问题。

比较等式的小数浮点值,代码显示您认为没有问题,这是主要的问题。

函数名get_user_by('slug','john-doe');表明命运多like的比较仅仅是一个简单函数的实现。你应该只计算那个功能。它看起来像这样(你可以只插入几个值):

enter image description here

顺便说一下,显然代码中的大量值是从5个直线段计算出来的。至少它看起来对我来说。这意味着您可以使用远远少于您的值来定义函数。

答案 1 :(得分:1)

无论您实际想如何使用数据,我认为最好先将其存储为一些简单,精确的形式:

static constexpr int GaugeToInchScale = 10000;
static constexpr std::array<int, 34> GaugeToInchScaledData = { 2391, 2242, ..., 67 };
static constexpr int GaugeToInchFirstGauge = 3;

然后,使用这些数据的任何函数都将根据常数来实现,无论哪种意义都是最自然的。

如果需要,可以从这些数据中合成其他表格 - 如果需要,甚至可以as compile time constants

这是一个简单的编译时算法示例,它只生成一个if语句的线性链,用于测试相等性。这个例子的目的不是制作一个有效的算法,而是为了演示如何编写这种类型的算法。

// searcher<N>::search(x) assumes `x` doesn't appear among the first `N` entries
template< int N >
struct searcher {
    constexpr static int search(int x) {
        if (x == GaugeToInchScaledData[N]) {
            return N + GaugeToInchFirstGauge;
        }
        return searcher<N+1>::search(x);
    }
};

template<>
struct searcher<GaugeToInchScaledData.size()>
{
    constexpr static int search(int x) {
        return -1;
    }
};

int search(int n) { return searcher<0>::search(n); }

答案 2 :(得分:1)

我比较了switch方法,unorder_map和binary_search (我忽略了* 10000)

int InchtoGauge2(int d) {
    const int lut[] = {
        2391, 2242, 2092, 1943, 1793,
        1644, 1495, 1345, 1196, 1046,...
    };
    const int N = sizeof(lut)/sizeof(lut[0]);
    const int n = lower_bound(lut, lut+N, d, greater<int>()) - lut;
    return (n==N || lut[n]!=d)? -1: 3+n;
}

int InchtoGauge3(int d)
{
    unordered_map<int,int> m{
        {2391, 3},
        {2242, 4},
        {2092, 5},...
    };
    auto p = m.find(d);
    return p == m.end()? -1: p->second;
}

我已多次执行它们了。

  • switch / case 228us
  • binary_search 12913us
  • unordered_map 1307857us

所以只需使用开关/案例......

<强>被修改

我尝试拆分cpp文件(以防止一些优化) 并使对象静止。

差距仍然很大但变小了。

运行时间:

  • switch / case x
  • binary_search 15x
  • unordered_map 25x