对象需要(A,b)数组,而客户端具有带有元素(A,b)的类数组

时间:2014-05-28 20:26:14

标签: c++

我正在尝试构建一个求解器对象。它打算执行的算法是:

  • 接受描述系统Ax = b的输入。
  • 使用最小二乘法求解x(对于所考虑的案例,系统是过度确定的)
  • 计算b' = Ax,给定最小二乘x
  • 时预期的b
  • 返回b'

其他一些约束

  • 客户端以压缩形式存储A的元素(由2个元素ayaz描述),但是它们需要扩展为完整的50个元素用于矩阵计算。因此,求解器对象具有内部A数组(保持扩展形式)
  • 并不浪费内存
  • ayazb存储为对象foo的元素的客户端代码,因此具有一个foo的数组比持有ayazb的几个数组。这种架构是不可协商的,这意味着:
    • 我无法创建一个简单的函数doEverything(double *ay, double *az, double *b)
    • 求解器对象必须具有内部b数组(用于提供矩阵数学函数 - 不同的foo::b元素是不可接受的)

我目前的课程要求正确使用以下公共职能:

  • void prepForInputWith(int nElements) - 调整内部数组的大小以允许nElements的空间(调用一次)
    • 如果没有调用此函数,该类非常智能,可以重新调整自身大小,但调用它可以省去每次添加新元素时重新分配的麻烦
  • void setAandB(double ay, double az, double b) - 设置A和b中的下一行数据(每个数据点调用一次)
  • void calculateXBestFit() - 将系统反转为x(称为一次)
  • double returnBPrime() - 返回下一个单元格的答案(每个数据点调用一次,并且必须以与setNextResult相同的顺序调用)

请注意,客户必须按照调用returnBPrime()的顺序调用setAandB(),因为A的条目(在setAandB()中计算并在calculateXBestFit()中使用)在returnBPrime()中计算b' = Ax时重复使用。删除此优化将使returnBPrime()可以按任何顺序调用,但会带来运行时惩罚。

我对此感到不满,因为:

  • 客户端代码似乎比它需要的更复杂
  • 在这种方法中,doEverything()方法中可以理所当然的一些事情是不可能的:

      在计算任何答案之前,可以调用
    • returnBPrime()
    • returnBPrime()可以被称为与setAandB()
    • 不同的次数

    这意味着

    • 该类需要检查它是否正确使用,使目标代码复杂化
    • 所有检查必须在运行时执行,而似乎应该有足够的信息来确定是否在编译时正确使用了类

有更优雅的方式吗?

1 个答案:

答案 0 :(得分:0)

这个类的接口规范似乎对类的客户端可以调用其函数的顺序设置了一些约束(如果他们希望得到有效的结果)。我无法想到在编译时强制执行该序列的任何方法。

您可以做的不是访问超出范围的数据。您显然需要某种内部计数器来说明setAandB()修改或返回每个数组的哪个元素 和returnBPrime()。事实上,我会让这些功能中的每一个使用不同的计数器, 我会让calculateXBestFit()将这两个计数器设置为零。 然后,对nElements的下一次returnBPrime()来电将返回b'的元素。按顺序,您可以拨打setAandB()另一个nElements以准备下一个电话 到calculateXBestFit()

有一些有用的运行时检查,但我认为它们的成本相当低。主要的一个 是范围检查returnBPrime()使用的计数器。一旦达到b&#39;中存储的数据的长度,后续的呼叫就不会尝试读取b&#39; (但如果您可以就此达成一致,可能会生成异常或错误消息),直到下一次调用calculateXBestFit()之后。只要此类的客户端持有合同,此运行时检查的成本就是if (counter < limit)形式的分支的成本。

还有setAandB()的运行时检查,但我认为你已经考虑了一个(因为你说如果需要的话,类会重新调整数组的大小)。

calculateXBestFit()设置每个数组的所有nElements元素之前,如果调用了setAandB(),您需要达成一致。在我看来,最好的行为是将setAandB()的调用次数视为所需的数组大小,而不管nElements的值是多少。这也意味着要记住calculateXBestFit()使用的数组的大小,以便returnBPrime()将使用该数字,而不是nElements,作为实际允许从b读取的值的数量&# 39;

顺便说一下,我还要calculateXBestFit()计算并存储b&#39;的内容。在此对象的另一个数组中。这意味着此次调用后对象发生的任何事情 - 除了对calculateXBestFit()的另一次调用 - 都不会影响对returnBPrime()的调用结果。

让我们看一下:这涵盖了多次调用setAandB(),调用setAandB()太少次,调用returnBPrime()太多次,甚至将调用交错到{{ 1}}调用returnBPrime()以解决下一个问题。关于我能想到的唯一剩下的明显错误是调用setAandB()太少次,结果就是客户端获得的数据少于本来应该的数据。我只看到一个你还没有承诺的运行时检查。

相关问题