3

3 次元のベクトルと測定単位を処理するための F# モジュールを定義したとします。

[<Measure>]
type m
[<Measure>]
type s
[<Measure>]
type v = m/s
[<Measure>]
type rad

type Vector3<[<Measure>] 'a> =
    {
    X : float<'a>
    Y : float<'a>
    Z : float<'a>
    }

そして、どこかにラジアンで表された角度があります:

let angle:float32<rad> = 0.5f<rad>

次に、角度を使用して Vector3 (速度) を宣言し、そのコンポーネントを計算する必要があります。私は次のようなものを試しました:

let velocity : Vector3<m/s> = { X = Math.Cos(angle);Y = Math.Sin(angle);Z = 0.0<m/s>} //don't compile

Vector3 は X と Y の値を期待しているが、Sin は float を返すため、上記のコードはコンパイルされません。

どうすればこの問題を解決できますか? 可能であれば、角度を速度に変換するときにコンパイラが正しいことを行うことを保証できるように、キャストの代わりに測定単位間の変換を実行したいと思います。

なにか提案を?

4

3 に答える 3

4

ここにいくつかの問題があります: cosは単位のない値を期待しているため、単位を外す必要がありますangle。速度がであり、 でfloatはないことを考えるとfloat32、 に直接変換することもできますfloat(これにより、単位が削除されます)。

次に、ユニットを元に戻す必要があります。測定単位の最初のバージョンでは、適切な測定値に 1 を掛けるだけでこれを行うことができました。これLanguagePrimitives.FloatWithMeasureはより正確ですが、少し冗長です。

let velocity =
 {
     X = angle |> float |> cos |> LanguagePrimitives.FloatWithMeasure<m/s> ;
     Y = angle |> float |> sin |> LanguagePrimitives.FloatWithMeasure<m/s> ;
     Z = 0.0<m/s> ;
 }

それはさておき、10ラジアンは面白い角度です...

cos(とsinが組み込まれていることに注意してください)

于 2011-11-29T09:41:20.657 に答える
1

可能であれば、角度を速度に変換するときにコンパイラが正しいことを行うことを保証できるように、キャストではなく測定単位間の変換を実行したいと考えています。

あなたは相反するものを求めます。測定単位は、型推論を使用してプログラム内の単位を強制することにより、プログラムの正確性を保証するのに役立ちます。そのため、変換は明示的に行う必要があります。

@Benjolが言ったように、次元データと無次元データの間で変換する必要があります。以下のコードは、単位値を掛けてからfloatに変換する非公式バージョンです。float<m/s>

let angle:float32<rad> = 0.5f<rad>

let velocity = {
                X = sin (float angle) * 1.0<m/s> ; 
                Y = cos (float angle) * 1.0<_> ; 
                Z = 0.0<_>
               } 

X の単位を指定するだけでよく、他の単位は の型宣言に基づいて推測されることに注意してくださいVector3

于 2011-11-29T10:05:40.433 に答える