使用F#测量单位从m / s转换为km / h

时间:2012-12-11 14:39:58

标签: f# units-of-measurement

我正在学习F# - 目前正在研究测量单位。我有一个简单的计算返回米每秒,我想引入一个函数将其转换为每小时公里。

我的代码如下所示:

[<Measure>] type kg
[<Measure>] type s
[<Measure>] type m
[<Measure>] type km
[<Measure>] type h            

let msToKmph(speed : float<m/s>) =
    (float speed) * 3.6<km/h>

let gravityOnEarth = 9.81<m/s^2>
let heightOfJump = 3.5<m>

let speedOfImpact = sqrt (2.0 * gravityOnEarth * heightOfJump)
let speedOfImpactKmh = msToKmph(speedOfImpact)

这是有效的 - 我得到8.28673639 m / s和29.832251 km / h。我不确定的是,这是表达不同单位之间关系的最佳方式。这可以更优雅地完成吗?

例如,行(浮动速度)从速度参数中移除单位信息,使msToKmph返回km / h。如果在进行计算之前我没有删除单位信息,则返回的单位为:km m /(h s)

2 个答案:

答案 0 :(得分:17)

首先,您的msToKmph完全不正确。虽然它返回了一个正确的返回值,它实际上正在做什么,只是 drop 原始<m/s>值转换为普通的无量纲 {{1然后将无量纲值乘以float

为了更好地表达UoM之间的关系,请考虑以下事项:

3.6<km/h>

请注意,所有“幻数”都封装在UoM转换器中,因此您的公式保持干净,例如它们只是操作值和常量,但UoM由编译器计算。

更新:UoM转换的理念是转换公式应该是具有物理意义的东西。经验法则是您的转换价值是否出现在参考书中。用简单的英语,let kmToM = 1000.0<m/km> // relation between kilometers and meters let hrToSec = 3600.0<s/h> // relation between seconds and hours let msToKmph(speed : float<m/s>) = speed / kmToM * hrToSec 从上面来看是没用的,但3.6<km/h>只是说,“1公里内有1000米”,这是有道理的。

您甚至可以像这样改进1000.0<m/km>

hrToSec

这将使每个值都成为参考书中的众所周知的价值。

答案 1 :(得分:4)

你是对的,删除单位信息是件坏事。您应该创建一些具有适当转换单位的常量。

let mPerKm = 1000.0<m/km>
let secondPerHour = 3600.0<s/h>

// val msToKmph : float<m/s> -> float<km/h>
let msToKmph(speed : float<m/s>) =
    speed / mPerKm * secondPerHour

对于kmm,通用解决方案是定义单位前缀k,以便它适用于以千克作为指标的许多UoM:

[<Measure>] type k

let kilo = 1000.0<1/k>
let secondPerHour = 3600.0<s/h>

// val msToKmph : float<m/s> -> float<k m/h>
let msToKmph(speed : float<m/s>) =
    speed / kilo * secondPerHour