“工业实力”C ++结构

时间:2015-02-26 22:31:02

标签: c++ struct constructor

我使用C ++已经有一段时间了。我被要求进行面试,为下采样程序创建一个C ++结构,它将满足以下接口:

struct  deterministic_sample
{
    deterministic_rate( double rate );
    bool operator()();
};

- 具有以下行为:

  • 我们有一个类的对象:deterministic_sample s;
  • 我们拨打s() N次,然后返回true次,M次。 M / N大致等于费率
  • 序列是确定性的,不是随机的,每次都应该相同
  • 该课程应该是“工业实力”,适合在繁忙的小溪中使用。

我的解决方案,版本2:

#include <iostream>
#include <cmath>
#include <climits>

using namespace std;

struct deterministic_sample
{
    double sampRate;
    int index;

    deterministic_sample() {
        sampRate = 0.1;
        index = 0;
    }

    void deterministic_rate( double rate ) {
        this->sampRate = rate;  // Set the ivar. Not so necessary to hide data, but just complying with the interface, as given...
        this->index = 0;  // Reset the incrementer
    };

    bool operator()() {

        if (this->index == INT_MAX) {
            this->index = 0;
        }

        double multiple = this->index * this->sampRate;

        this->index++;  // Increment the index

        if (fmod(multiple, 1) < this->sampRate) {
            return true;
        } else {
            return false;
        }

    };
};

int main()
{
    deterministic_sample s;  // Create a sampler
    s.deterministic_rate(0.253);  // Set the rate
    int tcnt = 0;  // Count of True
    int fcnt = 0;  // Count of False

    for (int i = 0; i < 10000; i++) {
        bool o = s();
        if (o) {
            tcnt++;
        } else {
            fcnt++;
        }
    }

    cout << "Trues: " << tcnt << endl;
    cout << "Falses: " << fcnt << endl;

    cout << "Ratio: " << ((float)tcnt / (float)(tcnt + fcnt)) << endl;  // Show M / N

    return 0;
}

采访者说这个v2代码“部分”解决了这些要求。 v1没有构造函数(我的错误),并没有处理int ivar的溢出。

我在这里错过了什么让这个课程更加健全/正确?我认为这是“工业实力”的一些方面,我错过了。

PS。对于任何道德类型,我已经提交了我的第二次机会尝试...这只是困扰我,知道为什么这是“部分”......

4 个答案:

答案 0 :(得分:3)

你拥有的东西远比必要复杂得多。您需要做的就是跟踪当前位置,并在超过阈值时返回true

struct deterministic_sample
{
    double sampRate;
    double position;

    deterministic_sample() : sampRate(0.1), position(0.0) {
    }

    void deterministic_rate( double rate ) {
        assert(rate <= 1.0); // Only one output is allowed per input
        sampRate = rate;  // Set the ivar. Not so necessary to hide data, but just complying with the interface, as given...
        // No need to reset the position, it will work with changing rates
    };

    bool operator()() {
        position += sampRate;
        if (position < 1.0)
            return false;
        position -= 1.0;
        return true;
    }
};

答案 1 :(得分:1)

使用unsigned并且整数溢出是一个明确定义的环绕。这在普通CPU上非常快。

我看到的第二个问题是浮点数和整数数学的混合。这不是很有效。将multiple存储为成员并执行multiple += rate可能更有效。这样可以节省一个整数到双倍的转换。

然而,fmod仍然非常昂贵。您可以通过保留int trueSoFar来避免这种情况。现在,到目前为止的费率为double(trueSoFar)/double(index),您可以double(trueSoFar)/double(index) > rate或更有效地检查trueSoFar> int(index * rate)。正如我们已经看到的,rate*index可以替换为multiple += rate

这意味着我们有一个双重加法(multiple +=),一个FP到int转换int(multiple)和一个整数比较。

[编辑] 您还可以通过保持rate的32/32有理逼近,并将其与实现的速率(再次存储为32/32比率)进行比较来完全避免FP数学。从a/b > c/d开始a*d > b*c时,您可以在这里使用64位乘法。更好的是,对于目标比率,您可以选择2 ^ 32作为固定分母(即unsigned long targetRate = rate*pow(2^32),b = 2 ^ 32隐式),以便您现在拥有unsigned long(unsigned long long(a)*index) >> 32) > trueSoFar。即使在32位CPU上,这也相当快。 >>32在那里是无操作。

答案 2 :(得分:0)

您的代码有几个问题:

  • 准确度:在10 000次迭代中,您获得0.2535。这是10000的误差5。如果速率为0.253,我预计10000的最大误差为4。

  • 不连续:当处理溢出时,你用0重新开始索引。因此会出现明显的不连续性。但当然,总的来说,它将是可以忽略的

  • 符合规范:您在更改采样率时随意决定从0重新启动。虽然这似乎是可以接受的,但这种行为并未明确要求。可以想象(特别是在工业环境中),如果稍微修改速率,输出将尽可能快地适应新速率,而不会失去与先前输出相比的连续性。

  • 语法:在两个成员函数定义之后存在不必要的;,并且使用不必要的this->来引用局部变量。当然没错,但......

这是另一种选择:

struct deterministic_sample
{
    double sampRate;
    unsigned long rtt; // tottal number of true returned
    unsigned long rts; // total answers 

    deterministic_sample() : sampRate (0.1), rtt(0), rts(0) { }

    void deterministic_rate(double rate) {
        sampRate = rate;   // continue output but with a new performance rate. 
    }

    bool operator()() {
        if (rts == LONG_MAX) {  // in case of owerflow
            rtt = 1000.0*rtt/rts; rts = 1000;  // restart, but minimizing discontinuity
        }
        bool ret = rts==0 || (double)rtt / rts < sampRate;  // catch up algorithm
        if (ret)    // update counters
            rtt++;
        rts++;
        return ret;
    }
};

答案 3 :(得分:0)

好的,所以似乎可以做出一些改进(当然),“工业强度”有一些含义,虽然没有具体的(可能是问题...),或者构造函数被错误命名在问题中(也可能)。

在任何情况下,没有人跳过我对构造函数的一些明显遗漏(比如,我看到有两种方法可以做一个C ++构造函数;你应该两个都做真的防弹,等等)

我想我只是交叉手指,希望我仍然可以进入软技能面试! 谢谢大家。