2010-11-30 7 views
6

「足」vs「インチ」や「cm」などの抽象概念を提供する甘い言語があるかどうか疑問に思っていました。Javaで次のようなことを検討していました。プログラミングの計算単位を保存する

u(56).feet() + u(26).inches() 

、結果として

17.7292メートルのようなものを得ることができます。

可能なアプローチの1つは、新しい値を作成するときに、すぐにメーターなどの「ベース」単位に変換することで、簡単に追加できます。

しかし、私はむしろ、単位を維持する能力を持っているでしょうので、何かのよう

u(799.95555).feet() - u(76).feet() 

戻り

723.95555 feet 

と、この問題はのように思えるのでない

243.826452 meters - 23.1648 meters = 220.661652 meters 

//220.661652 meters to feet returns 723.955551 feet 

それは本当に一般的でしょう、どんなフレームワーク、または処理する存在するプログラミング言語さえありますか?これはエレガントに?

私は自分のメソッドにあるようにユニットを追加し、一致するユニットを一緒に追加し、要求されたときには[add/subtract/multiply/divide]に変換することしかできないと思います。減算:

//A 
{ 
    this.inches = 36.2; 
    this.meters = 1; 
} 

//total length is 1.91948 m 

私は値

//B 
{ 
    this.inches = 0.8; 
    this.meters = 2; 
} 

//total length is 2.02032 m 

とオブジェクトBにこれを追加し、私は

ある新しいオブジェクトを取得する場合10

これは完全に素晴らしいですが、問題がない場合はいつでも変換できます。しかし、このような乗算が失敗するなどの操作...

//A * B = 3.87796383 m^2 
{ 
    this.inches = 28.96; 
    this.meters = 2; 
} 

// ...but multiplying piece-wise and then adding 
// gives you 2.01868383 m^2, assuming you make 2m*1m give you 2 m^2. 

は、だから私は本当にその例に見せたかったすべてはその

(A1 + A2) * (Z1 + Z2) is not (A1 * Z1) + (A2 * Z2) 

だったと私は、これは1がAに変換することがある意味かなり確信しています彼らが掛け算や分割をしたい場合には、共通の単位である。

*/は失敗するため、この例ではほとんどの場合反射的な回答を抑止し、最後の瞬間に変換する前にピース単位で加算または減算しています。

tl; dr:プログラミングでユニットを保存するための巧妙な方法はありますか?メソッド/ルーチンに名前を付ける巧妙な方法があるので、私が追加や減算などを理解するのは簡単ですか?

答えて

5

私は実際にそのような言語がありますが、私はそれを自分で使っていません。
Frinkと呼ばれています。

同じ次元で異なる単位を混在させるだけでなく、いくつかの異なる物理的測定値で操作することもできます。そのサイトのsample calculationsは楽しい読書です。私は特にSupermanビットのようです。

+1

これはJavaから簡単に使用することもできますし、真剣な会議で話を30分のおならの冗談に変えることを管理している言語デザイナーは、無料のStackOverflow PRに値する! –

0

を参照してください可能性があります。部分ユーティリティをたくさん見つけることができます(UNIXにはいくつかのものがあります)。 NISTはユニットマークアップ言語を開発していましたが、それは少なくとも10年の料理でした。

これを行うには、ユニットが定義されているオントロジーと変換のルールが適切に必要です。また、接頭辞も扱わなければなりません。

物理科学(SI単位)に固執する場合は、基本単位型が7つ(場合によっては8つ)、派生量が22種類あります。しかし、それらを組み合わせることができる無数の方法もあります。例えば、加速度の変化率は、ある人によっては「ジャーク」と呼ばれます。原則として、不特定多数の派生物を持つことができます。

通貨単位はありますか? ...

+0

甘いものはまだありません=( – sova

+0

あなたの意見では、何が欠けているのですか? –

2

多くの関数型言語を参照してください。ユニットの保存のこの種の型を作成することができます。

*Main> let a1 = 1 :: Feet 
*Main> let a2 = 2 :: Feet 
*Main> let a3 = 3 :: Meters 
*Main> a1+a2 
Feet 3.0 
*Main> a1+a3 

<interactive>:1:3: 
    Couldn't match expected type `Feet' against inferred type `Meters' 
    In the second argument of `(+)', namely `a3' 
    In the expression: a1 + a3 
    In the definition of `it': it = a1 + a3 
*Main> 

今あなたがに変換する変換型クラスを作成することができますし、:

-- you need GeneralizedNewtypeDeriving to derive Num 
newtype Feet = Feet {unFeet :: Float} deriving (Eq, Show, Num) 
newtype Meters = Meters {unMeters :: Float} deriving (Eq, Show, Num) 

今、各ユニットは、独自の型で、あなただけの同じ型の値に対して操作を実行できますHaskellで任意の測定タイプから

class LengthMeasure unit where 
    untype :: unit -> Float 
    toFeet :: unit -> Feet 
    toFeet = Feet . (* 3.2808) . untype . toMeters 
    toMeters :: unit -> Meters 
    toMeters = Meters . (* 0.3048) . untype . toFeet 

instance LengthMeasure Feet where 
    untype = unFeet 
    toFeet = id 

instance LengthMeasure Meters where 
    untype = unMeters 
    toMeters = id 

今、私たちは自由にタイプ間で変換することができます

*Main> a1+toFeet a3 
Feet {unFeet = 10.842401} 

もちろん、こんなことをするパッケージはHaskellのavailableです。

既にJavaを使用しているので、おそらくScalaやClojureは同様の機能を提供するでしょうか?

関連する問題