7

StackOverflowの群集。非常に自由なソフトウェア設計の質問があります。

私はしばらくの間これに対する寛大な解決策を探していました、そして私はここの誰かが問題への素晴らしい洞察を持っているかどうか疑問に思いました。これはデータ構造のパズルのようなものだと考えてください。

私がやろうとしているのは、任意の単位から任意の単位に変換できる単位変換器を作成することです。字句解析と構文解析がすでに行われていると仮定します。いくつかの簡単な例:

Convert("days","hours")           // Yields 24
Convert("revolutions", "degrees") // Yields 360

物事をもう少し複雑にするには、入力間のあいまいさをスムーズに処理する必要があります。

Convert("minutes","hours")        // Yields (1/60)
Convert("minutes","revolutions")  // Yields (1/21600)

物事をさらに楽しくするには、すべての可能性を列挙する必要なしに、複雑なユニットを処理する必要があります。

Convert("meters/second","kilometers/hour")
Convert("miles/hour","knots")
Convert("Newton meters","foot pounds")
Convert("Acre feet","meters^3")

正解も不正解もありません。これを実現するためのアイデアを探しています。力ずくの解決策は常にありますが、シンプルでスケーラブルなエレガントなものが必要です。

4

6 に答える 6

3

私はハッシュテーブル (または永続化されたルックアップ テーブル - 実装方法は自由に選択) から始めます。これは、入力したい数のペア間で単位変換を実行します。考えられるすべてのペアを入力する場合、これはブルート フォース アプローチです。

部分的なペアしかない場合は、必要なペアを検索して組み合わせを見つけることができます。たとえば、ハッシュテーブルに次の 2 つのエントリがあるとします。

Feet|Inches|1/12
Inches|Centimeters|2.54

ここで、フィートをセンチメートルに変換したい場合は、簡単なグラフ検索を行います。頂点はフィート、インチ、センチメートルで、辺は 1/12 と 2.54 の変換係数です。この場合の解決策は、2 つのエッジ 1/12、2.54 です (もちろん、乗算によって結合されます)。必要に応じて、グラフ パラメーターを使用してより洗練されたものにすることができます。

もう 1 つのアプローチは、抽象的推論を適用することかもしれません。これについては、代数的問題解決者に関する AI のテキストを調べてください...

編集:複合ユニットのアドレス指定

簡単な問題: 「エーカー」を「メートル^2」に変換する

この場合、キーは長さの単位について話していることを理解しているので、「長さ」または「面積」の単位タイプのテーブルに新しい列を挿入しないでください。これにより、検索スペースを削減するための簡単な列が得られるため、以前のケースでもパフォーマンスが向上します。

ここでのコツは、長さ^2 = 面積を理解することです。このメタデータを格納する別のルックアップを追加してみませんか:

Area|Length|Length|*

これをプライマリ ユニット テーブルと結合します。

Meters|Feet|3.28|Length
Acres|Feet^2|43560|Area

したがって、アルゴリズムは次のようになります。

  • 解は m^2 で、これは m * m で、長さ * 長さです。
  • 入力は面積であるエーカーです。
  • メタ テーブルで m を検索し、長さ * 長さのマッピングを見つけます。より複雑な例では、複数の有効なマッピングが存在する場合があることに注意してください。
  • 解に Acres->Feet^2 の変換を追加します。
  • Feet->M に対して元のグラフ検索を実行します。

ご了承ください:

  • アルゴリズムは、機能する基本的なドメインとして面積と長さのどちらを使用するかを認識しません。ヒントを提供するか、両方のスペースを検索させることができます。
  • メタテーブルは少し力ずくのようになります。
  • タイプの混合 (例: 抵抗 = 電圧 / 電流) を開始したり、非常に醜いことを行って単位系 (例: FooArea = メートル * フィート) を混合したりする場合は、メタ テーブルをよりスマートにする必要があります。
于 2010-07-06T21:37:11.580 に答える
2

どのような構造を選択するにしても、その選択は、好みの実装 (OO ? 機能 ? DBMS テーブル ?) によって決まる可能性があります。ユニット自体の構造を特定する必要があると思います。

たとえば、時速 1000km の測定値にはいくつかのコンポーネントがあります。

  • スカラーの大きさ、1000;
  • 接頭辞、この場合はキロ。と
  • 次元、この場合は LT^(-1)、つまり長さを時間で割ったもの。

単位を使用した測定のモデリングでは、少なくともこの複雑さを把握する必要があります。

すでに提案されているように、使用する単位の基本セットが何であるかを確立する必要があり、SI 基本単位はすぐにそれ自体を提案します。モデリング単位のデータ構造は、これらの基本単位で定義されます。したがって、次のようなエントリを使用してテーブルを定義できます (ここでは RDBMS を考えますが、好みの実装に簡単に変換できます)。

unit name      dimension                 conversion to base

foot           Length                    0.3048
gallon(UK)     Length^3                  4.546092 x 10^(-3)
kilowatt-hour  Mass.Length^2.Time^(-2)   3.6 x 10^6

など。また、プレフィックス (キロ、ナノ、メガ、ミビなど) を乗数に変換するための表と、各次元の基本単位の表 (つまり、メートルは長さの基本単位、秒時間など)。feetまた、単に他のユニットの同義語であるなどのユニットに対処する必要があります。

もちろん、ディメンションの目的は、変換やその他の操作 (2 feetへの追加など3.5 metres) が釣り合っていることを確認することです。

そして、さらに読むために、Cardarelli によるこの本をお勧めします。

コメントに応じて編集...

私は(実装固有の)解決策を提案することから離れようとしているので、もう少しワッフルします。キロワット時などの複合単位は問題を引き起こします。kilowatt1 つのアプローチは、やなどの複数の単位式で測定値にタグを付けhour、それらを結合するためのルールを作成することmultiplication です。有効な単位のセットを、アプリケーションのドメインで最も一般的な単位に制限する方がよい場合があります。

混合単位での測定の扱いに関しては、単位の次元を定義する目的は、適切な操作のみが単位を含む測定に適用できるようにするための手段を提供することです。したがって、2 つの長さ (L+L) を加算することは賢明ですが、長さ (L) と体積 (L^3) は加算しません。一方、体積を長さで割ることは理にかなっています (面積 (L^2) を取得するため)。また、平方メートルあたりのキロワット時などの奇妙な単位が有効かどうかを判断するのは、アプリケーション次第です。

最後に、私がリンクしている本はすべての可能性を列挙しています。ユニットを使用する最も賢明なアプリケーションは、選択のみを実装すると思います。

于 2010-07-06T22:17:32.510 に答える
0

ある種のトリプルで変換に関するデータを保持したいとします(fstUnit, sndUnit, multiplier)

単一単位変換の場合:いくつかのハッシュ関数を使用しO(1)て単位構造を数値に変更してから、すべての乗数を行列に入れます(反射は同じですが、逆になっているため、右上の部分だけを覚えておく必要があります)。

複雑なケースの場合:例1. m/sからkm/h。行列で(m、km)をチェックし、次に(s、h)をチェックして、結果を乗算します。例2.m^3からkm^3。(m、km)をチェックして、3乗します。

もちろん、フィールドとボリュームのようにタイプが一致しない場合、いくつかのエラーが発生します。

于 2010-07-06T21:44:40.750 に答える
0

すべての基本単位の変換係数と指数をとる単位のクラスを作成できます(これにはメートル法を使用することをお勧めします。これにより、作業が楽になります)。例:疑似Javaの場合:


public class Unit {
   public Unit(double factor, int meterExp, int secondExp, int kilogrammExp ... [other base units]) {
     ...
   }
}

//you need the speed in km/h (1 m/s is 3.6 km/h):
Unit kmPerH = new Unit(1 / 3.6, 1, -1, 0, ...)

于 2010-07-06T21:44:42.497 に答える
0

これらのフィールドを持つテーブルがあります。

conversionID
fromUnit
toUnit
multiplier

サポートしたいすべての変換を保存するために必要な行数

複数ステップのプロセス (華氏から摂氏) をサポートする場合は、次のようなフィールドを持つ、conversionStep と呼ばれる単位テーブルとの 1 対多の関係が必要になります。

conversionID
sequence
operator
value

1 セットの変換を保存したいが、保存のように複数ステップの変換をサポートする場合

Feet|Inches|1/12
Inches|Centimeters|2.54

フィートからセンチメートルへの変換をサポートするには、変換計画を別のテーブルに保存します。

conversionPlanID
startUnits
endUnits
via

あなたの行は次のようになります

1 | feet | centimeters | inches
于 2010-09-30T15:47:53.957 に答える
0

すべての量の標準単位を選択することから始めます (たとえば、長さのメートル、力のニュートンなど)。次に、その単位へのすべての変換係数をテーブルに格納します。

次に、たとえば、日を時間に変換するには、1 日あたりの秒数と 1 時間あたりの秒数の変換係数を見つけ、それらを割って答えを見つけます。

あいまいさについては、各単位を測定するすべてのタイプの量に関連付けることができ、どの変換を行うかを決定するために、これらの 2 つのタイプのセットの共通部分を取得します (0 または複数のタイプが残っている場合は、エラーを吐き出します)

于 2010-07-06T21:31:46.347 に答える