2009-12-12 2 views
13

단위를 보존하는 유형 변환 함수가 내장되어 있습니까? 그렇다면 어떻게 만들 수 있습니까? 예를 들어이 코드를 사용하면 intWithSecondsMeasure를 부동 소수점 형으로 캐스팅하고 계수를 잃지 않고 1.0<s>을 곱하는 방법은 무엇입니까?F # 측정 단위, 측정 유형을 잃지 않고 캐스팅

[<Measure>] type s 
let intWithSecondsMeasure = 1<s> 
let justAFloat = float intWithSecondsMeasure 

답변

11

@kvb에서 제공하는 대답은 틀림없이 작동하지만이 변환에는 unbox 연산자를 사용하지 않는 것이 좋습니다. 더 나은, 내장 된 방식으로 내장 된 은 일리노이에 NOP로 컴파일되어야한다고 생각합니다.하지만 확인되지는 않았지만 unbox는 아마 IL에서 unbox 명령으로 끝나기 때문에 런타임 형식 검사를 추가합니다.

F #에서 단위 변환을 수행하는 가장 좋은 방법은 LanguagePrimitives.TypeWithMeasure (MSDN)입니다.

let inline float32toFloat (x:float32<'u>) : float<'u> = 
    x |> float |> LanguagePrimitives.FloatWithMeasure 
+0

IL을 추가했습니다. 질문과 일치하도록 int에서 부동으로 캐스팅하십시오. http://stackoverflow.com/a/21802111/17919 – gradbot

8

나는 그것을 할 수있는 기본 방법이 생각하지 않습니다,하지만 당신은 쉽게 자신의 단위 보존 변환 기능을 정의 할 수 있습니다 :

let float_unit (x:int<'u>) : float<'u> = unbox float x 
let floatWithSecondsMeasure = float_unit intWithSecondsMeasure 
3

이 질문에 대한 내 대답을 참조하십시오 :

,861 :

Unit-safe square roots

이 오늘 제안
+0

윌 뭔가 도서관에 가서? 분명히 계획된 FloatWithMeasure의 관점에서 쓸 수 있지만 분명히 직접 사용할 수있는 기능을 갖는 것이 더 낫습니다. –

+0

이 대답은 이제 경고를줍니다. "이 유형 테스트 또는 다운 캐스트는 측정 단위 'u'를 무시합니다. – gradbot

4

나는 kvb와 Johannes의 답변에서 코드를 컴파일했습니다.

요하네스 추가 괄호

let float32toFloat (x:int<'u>) : float<'u> = 
    x |> float |> LanguagePrimitives.FloatWithMeasure 

.method public static float64 float32toFloat(int32 x) cil managed 
{ 
    // Code size  3 (0x3) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: conv.r8 
    IL_0002: ret 
} // end of method Program::float32toFloat 

KVB 응답에 응답합니다.

let float_unit (x:int<'u>) : float<'u> = unbox (float x) 

.method public static float64 float_unit(int32 x) cil managed 
{ 
    // Code size  13 (0xd) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: conv.r8 
    IL_0002: box  [mscorlib]System.Double 
    IL_0007: unbox.any [mscorlib]System.Double 
    IL_000c: ret 
} // end of method Program::float_unit 

KVB 응답

let float_unit (x:int<'u>) : float<'u> = unbox float x 

.method public static float64 float_unit(int32 x) cil managed 
{ 
    // Code size  19 (0x13) 
    .maxstack 8 
    IL_0000: newobj  instance void Program/[email protected]::.ctor() 
    IL_0005: call  !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGeneric<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,float64>>(object) 
    IL_000a: ldarg.0 
    IL_000b: tail. 
    IL_000d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,float64>::Invoke(!0) 
    IL_0012: ret 
} // end of method Program::float_unit 
이 서명