繁体   English   中英

关于如何保持“计算”很多“依赖”参数的建议

[英]suggestions how to keep “calculated” a lot of “dependent” parameters

我有几个指标需要“始终保持最新”。 即,当发生任何更改时,我需要重新计算“从属”。 我有几个级别,仅在计算上一个级别时才应计算每个下一个级别。 让我通过这张照片来解释一下:

设计

在某个时候,假设法郎改变了。 然后,我们应该:

  1. 法郎/第纳尔
  2. 法郎/第纳尔/比索

或者,如果一次更改比索,法郎和第纳尔,那么我们应该:

  1. 法郎/第纳尔
  2. 法郎/第纳尔/比索
  3. 计算比索+欧元/(欧元+美元)

因此,无论何时遇到Level 0任何东西,我们都应该重新计算所有其他级别。

  • 我们应该只计算必填项。 如果欧元变动,我们不需要重新计算法郎/第纳尔
  • 我们不应该计算超过一次。 如果一次更改欧元和美元,我们应该只计算一次欧元+美元(而不是两次)。

最直接的解决方案是:

  • 将每个级别存储在数组中
  • 对于下一个级别的阵列曲目“监听器”中的每个项目(可能会比较困难,因为例如,比索具有不同级别的听众-级别2的法郎/第纳尔/比索和级别3的比索+欧元/(欧元+美元),所以两个-需要维度数组。)
  • 如果项目被重新计算,则将其所有侦听器也标记为也被重新计算
  • 从级别0转到最后一级,并重新计算标记为要重新计算的项目(最初更新的项目是要重新计算的市场,例如比索)。

我想我的问题是众所周知的,也许您可​​以向我建议一般的解决方案。 我不想重新发明轮子:)谢谢!

我认为基于级别的方法是合理的,前提是侦听器始终处于较低级别。

这个想法:

有一个包含您的实际数据的2D数组,第一个索引是级别,第二个索引是级别上的位置。 让每个元素都有一个willBeRecalculated标志。

每个级别都有一个toBeRecalculated列表(因此是一个列表数组)。

对于每个元素,都有一个包含2个整数的元素(侦听器)列表-一个用于级别,一个用于索引。

对于每个要修改的元素,在适当的级别将元素添加到toBeRecalculated并将willBeRecalculated设置为true。

然后从第一级到最后一级进行toBeRecalculated ,重新计算每个元素,将其willBeRecalculated设置为false,然后对于每个侦听器,查找适用的元素,如果willBeRecalculated为true,则什么也不做,否则,将willBeRecalculated设置为true并添加toBeRecalculated在其(侦听器)级别上重新计算。

这种方法不会遍历所有数据来检查需要修改/已修改的内容,它仅检查适用的元素,并且没有重复的计算。

例:

为了这:

(对于我的缩写,我只是拿了每个单词的第一个字母。我使用的是0索引数组)

实际数据:

[[E, U, P, F, D],
 [E+U, F/D],
 [E/E+D, F/D/P],
 [P+E/E+U]
]

听众:

E:[(1,0), (2,0)] // E+U and E/E+U
U:[(1,0)] // E+U
P:[(2,1), (3,0)]
F:[(1,1)]
D:[(1,1)]
E+U:[(2,0)]
F/D:[(2,1)]
E/E+U:[(3,0)]

修改EU

EU添加到toBeRecalculated[0]并将两者的willBeRecalculated设置为true。

进行toBeRecalculated[0]

修改E ,将willBeRecalculated设置为false并将E+UwillBeRecalculated为true并将其添加到toBeRecalculated[1]并将E/E+UwillBeRecalculated为true并将其添加到toBeRecalculated[2]

修改U ,将它的willBeRecalculated设置为false,然后检查E+UwillBeRecalculated ,看它是正确的,所以什么也不做。

然后进行toBeRecalculated[1] 修改E+U ,将willBeRecalculated设置为false并检查E/E+UwillBeRecalculated并查看它的正确性,因此不执行任何操作。

注意:

最好让侦听器作为元素的指针,而不是级别和索引变量。

好吧,当您说要处理关卡时,就会想到某种树数据结构。

但是对于您的问题,我认为对某种有向无环图建模是可行的。

您的图表可能看起来像这样(所有方向都朝下)。

                             root 
                   /     /     |     \     \
                 E      U      P     F      D
                 \     /
                  \   /
              (Euro + Usd)

如果像树形数据结构那样遍历该对象,则每次对货币进行的更新时,每个转换率都将精确更新一次。

您所描述的内容可以通过反应式编程语言轻松实现

Qt的QML还提供了一种属性绑定机制,可用于UI。

查看Qt属性绑定和其他反应式语言的实现可能会为您提供一些实现想法。

Wikipedia页面标识用于Java,.NET,Python,Java,C ++和许多其他语言的反应式编程的库。

我认为您可以在此处使用多态。 有一个货币列表,每个货币都包含一个向量,该向量带有所有去污元素的指针(指向基类)。

基类迫使它们包括一个函数update() ,该函数在每次更新当前货币时都会调用。

反作用元素依次具有它们所依赖的每种货币的指针,并在其update()实现中使用它们来更新自身。

#include<iostream>
#include <vector>
class c_node_combi_base;
class currency
{
  std::vector<c_node_combi_base*> m_dependant;
  double m_val;
public:
  double value (void) const { return m_val; }
  void reg (c_node_combi_base * p) { m_dependant.push_back(p); }
  void update (double val);
};
class c_node_combi_base
{
  std::vector<currency*> currencies;
public:
  virtual void update (void) = 0;
};

template<size_t N, typename OP> // templated to differentiate types of nodes
class currency_node : public c_node_combi_base 
{ 
};

struct divide_d 
{
  double operator() (const double x, const double y) const {return x/y;}
};

template<typename OPT> // node type 2
class currency_node<2u, OPT> 
  : public c_node_combi_base
{
  currency *A, *B;
  OPT _op;
  double m_val;
public:
  currency_node (currency * a, currency * b)
    : A(a), B(b), _op(), m_val(_op(A->value(), B->value())) 
  {
    A->reg(this);
    B->reg(this);
  }
  void update (void) 
  { 
    m_val = _op(A->value(), B->value());
  }

  double value (void) { return m_val; }

};

void currency::update (double value) 
{
  m_val = value; 
  for (size_t i=0; i<m_dependant.size(); ++i)
  {
    m_dependant[i]->update();
  }
}

这样可以:

int main (void)
{
  currency franc, dinar;
  franc.update(9.9);
  dinar.update(3.3);
  currency_node<2, divide_d> franc_dinar(&franc, &dinar);
  std::cout << franc_dinar.value() << std::endl;
  dinar.update(1.1); // updates franc_dinar automatically
  std::cout << franc_dinar.value() << std::endl;
}

印刷:

3
9


也许您可以拥有货币的std::vector<std::weak_ptr> ,而每个节点持有每种货币的std::shared_ptr ,因此除非没有其他节点引用,否则这些货币可能不会超出范围/被销毁他们

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM