8

「常に最新」である必要がある指標がいくつかあります。つまり、何かが変更された場合、「従属」を再計算する必要があります。前のレベルが計算されたときにのみ、次の各レベルを計算する必要があるいくつかのレベルがあります。この輝く写真で説明しましょう:

デザイン

ある時点でフランが変わったとします。次に、次のことを行う必要があります。

  1. カルク・フラン / ディナール
  2. カルク・フラン / ディナール / ペソ

または、ペソ、フラン、ディナールが一度に変更された場合は、次のようにする必要があります。

  1. カルク・フラン / ディナール
  2. カルク・フラン / ディナール / ペソ
  3. calc ペソ + ユーロ / (ユーロ + 米ドル)

そのため、何かが変更された場合Level 0は常に、他のすべてのレベルを再計算する必要があります。しかし

  • 必要な項目だけを計算する必要があります。ユーロが変更された場合、フラン/ディナールを再計算する必要はありません
  • 何回も計算するべきではありません。ユーロと米ドルが一度に変更された場合、ユーロ + 米ドルを 1 回だけ (2 回ではなく) 計算する必要があります。

最も簡単な解決策は次のとおりです。

  • 各レベルを配列に格納する
  • 配列トラック内の各項目について、次のレベルからの「リスナー」を追跡します (たとえば、ペソにはさまざまなレベルのリスナーがいるため、困難になる可能性があります-レベル2のフラン/ディナール/ペソとレベル3のペソ+ユーロ/(ユーロ+米ドル)なので、2つ-次元配列が必要です..)
  • アイテムが再計算された場合は、すべてのリスナーも再計算されるようにマークします
  • レベル 0 から最後のレベルに移動し、再計算するようにマークされた項目を再計算します (最初に更新された項目は、ペソなどの再計算される市場です)。

私の問題はよく知られていると思います。おそらく、よく知られている一般的な解決策を提案してください。私は車輪を再発明したくありません:)ありがとう!

4

4 に答える 4

2

レベルを扱っていると言うと、ある種のツリー データ構造が思い浮かびます。

しかし、あなたの問題については、ある種の有向非巡回グラフをモデル化するとうまくいくと思います。

グラフは次のようになります (すべての方向が下向きです)。

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

ツリー データ構造のようにこれをトラバースすると、通貨が更新されるたびに、各換算レートが 1 回だけ更新されます。

于 2013-07-18T14:28:18.930 に答える
0

ここでポリモーフィズムを使用できると思います。通貨のリストがあり、それぞれがすべての依存要素の (基本クラスへの) ポインターを持つベクトルを保持します。

update()基本クラスは、現在の通貨が更新されるたびに呼び出される関数を含めるよう強制します。

depedant 要素は、依存する各通貨のポインターを持ち、これらを使用して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各通貨の を保持している間、通貨の を保持できるため、通貨を参照するノードがなくなるまで、通貨がスコープ外に出たり破棄されたりすることはありません

于 2013-07-18T15:10:46.040 に答える
0

あなたが説明していることは、リアクティブプログラミング言語で簡単に実現できます。

Qt の QML は、UI に対してこれを実現するプロパティ バインディング メカニズムも提供します。

Qt のプロパティ バインディングやその他のリアクティブ言語の実装を見ると、実装のアイデアが得られるかもしれません。

ウィキペディアのページでは、Javascript、.NET、Python、Java、C++、および他の多くの言語でのリアクティブ プログラミング用のライブラリも特定されています。

于 2013-07-18T14:54:46.890 に答える