Преобразование из м / с в км / ч с использованием единиц измерения F #

Я изучаю 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 м / с и 29,832251 км / ч. В чем я не уверен, так это в том, что это лучший способ выразить отношения между разными единицами. Можно ли это сделать изящнее?

Например, строка делает (скорость с плавающей запятой), чтобы удалить информацию о единицах измерения из параметра скорости, чтобы вернуть msToKmph в км / ч. Если бы я не удалил информацию о единицах измерения перед выполнением вычислений, возвращенная единица измерения была бы: км м / (ч с)


person Jonas Follesø    schedule 11.12.2012    source источник
comment
Вероятно, вы захотите опубликовать это на стековой бирже CodeReview. codereview.stackexchange.com В остальном, я думаю, ваш подход хорош.   -  person Onorio Catenacci    schedule 11.12.2012
comment
Я сам их не использовал, но я бы определил функции преобразования между единицами одного и того же типа (например, длиной), используя отношения, выраженные с использованием соответствующих единиц (например, let mToKm(length: float<m>) = length * 0.001<km/m>), а затем построил бы другие преобразования на основе этих простых.   -  person Damien_The_Unbeliever    schedule 11.12.2012


Ответы (2)


Во-первых, ваш msToKmph совершенно неверен. Несмотря на то, что он возвращает правильное возвращаемое значение, на самом деле он просто отбрасывает исходное значение <m/s> путем преобразования в простое, безмерное float, а затем умножает безмерное значение до 3.6<km/h>.

Чтобы лучше выразить отношения между 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

Обратите внимание, что все «магические числа» инкапсулированы в конвертерах UoM, поэтому ваши формулы остаются чистыми, например они просто оперируют значениями и константами, но UoM рассчитываются компилятором.

Обновление: Философия преобразования UoM заключается в том, что формулы преобразования должны быть что-то, что имеет физический смысл. Эмпирическое правило заключается в том, отражена ли ценность вашей конверсии в справочниках. Говоря простым языком, 3.6<km/h> сверху бесполезно, но 1000.0<m/km> просто говорит: «В 1 км 1000 м», что имеет смысл.

Вы даже можете улучшить hrToSec вот так:

let hrToSec2 = 60.0<s/minute> * 60.0<minute/h>

Это сделает каждую ценность известной в справочниках.

person bytebuster    schedule 11.12.2012

Вы правы, что удалять информацию о юнитах - это плохо. Вы должны создать несколько констант с соответствующими единицами преобразования.

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

Для km и m общим решением является определение префикса единицы измерения k, чтобы он работал для многих единиц измерения, в которых в качестве метрики используется килограмм:

[<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
person pad    schedule 11.12.2012
comment
Никогда не думал о килограммах, отличная идея. Хотя я бы позвонил hourPerSecond secondPerHour. - person Benjol; 12.12.2012
comment
kilo - отличная идея, я думал об этом некоторое время назад. Я застрял на составных значениях типа km^2, которые оказались kilo^2 * m^2. Это не проблема для типичных единиц измерения СИ, но для практических расчетов это может быть затруднительно. Как вы вообще предлагаете смягчить это? - person bytebuster; 12.12.2012
comment
@bytebuster: Вы правы. Это место, где km выглядит лучше, чем k m. Я не знаю, как это обойти. - person pad; 12.12.2012