Ölçü Birimleri
F# dilinde kayan nokta ve işaretli tamsayı değerleri, genellikle uzunluk, hacim, kütle vb. belirtmek için kullanılan ilişkili ölçü birimlerine sahip olabilir. Birimlerle miktarları kullanarak, derleyicinin aritmetik ilişkilerin doğru birimlere sahip olduğunu doğrulamasını sağlarsınız ve bu da programlama hatalarını önlemeye yardımcı olur.
Not
Bu örnekler ölçü birimlerini içeren aritmetik hesaplamalarda doğruluğu gösterir. Bu özellik, FSharp.UMX projesi gibi bir yaklaşımla diğer türlere sıfır gösterim maliyetleriyle tür güvenli ek açıklaması eklemek için de kullanılabilir.
Sözdizimi
[<Measure>] type unit-name [ = measure ]
Açıklamalar
Önceki söz dizimi birim adını ölçü birimi olarak tanımlar. İsteğe bağlı bölüm, önceden tanımlanmış birimler açısından yeni bir ölçü tanımlamak için kullanılır. Örneğin, aşağıdaki satır ölçüyü cm
(santimetre) tanımlar.
[<Measure>] type cm
Aşağıdaki satır ölçüyü ml
(mililitre) santimetre küp (cm^3
) olarak tanımlar.
[<Measure>] type ml = cm^3
Önceki söz diziminde ölçü, birimleri içeren bir formüldür. Birimleri içeren formüllerde tamsayı güçleri desteklenir (pozitif ve negatif), birimler arasındaki boşluklar iki birimin çarpımını gösterir, *
ayrıca birim çarpımını gösterir ve /
birimlerin bir kısmını gösterir. Karşılıklı birim için negatif bir tamsayı gücü veya /
birim formülün paydası ile paydası arasındaki ayrımı gösteren bir kullanabilirsiniz. Paydadaki birden çok birim parantez içinde olmalıdır. sonrasında /
boşluklarla ayrılan birimler paydanın bir parçası olarak yorumlanır, ancak bir'i *
izleyen birimler paydanın bir parçası olarak yorumlanır.
Boyutsuz miktarı belirtmek için tek başına veya paydaki gibi diğer birimlerle birlikte birim ifadelerinde 1 kullanabilirsiniz. Örneğin, bir oranın birimleri olarak yazılabilir 1/s
ve burada s
saniyeler gösterilir. Parantezler birim formüllerinde kullanılmaz. Birim formüllerinde sayısal dönüştürme sabitleri belirtmezseniz; ancak, birimlerle dönüştürme sabitlerini ayrı ayrı tanımlayabilir ve bunları birim işaretli hesaplamalarda kullanabilirsiniz.
Aynı anlama gelen birim formülleri çeşitli eşdeğer yollarla yazılabilir. Bu nedenle, derleyici birim formüllerini tutarlı bir forma dönüştürür; bu da negatif güçleri karşılıklılara dönüştürür, birimleri tek bir payda ve paydaya gruplandırıp birimleri pay ve paydada alfabetik olarak alfabetik hale getirir.
Örneğin, birim formülleri kg m s^-2
ve m /s s * kg
her ikisi de öğesine kg m/s^2
dönüştürülür.
Kayan nokta ifadelerinde ölçü birimleri kullanırsınız. Kayan nokta numaralarının ilişkili ölçü birimleriyle birlikte kullanılması başka bir tür güvenliği düzeyi ekler ve zayıf yazılan kayan nokta sayıları kullandığınızda formüllerde oluşabilecek birim uyuşmazlığı hatalarını önlemeye yardımcı olur. Birim kullanan bir kayan nokta ifadesi yazarsanız, ifadedeki birimler eşleşmelidir.
Aşağıdaki örneklerde gösterildiği gibi, köşeli ayraç içindeki birim formülüyle değişmez değerlere açıklama ekleyebilirsiniz.
1.0<cm>
55.0<miles/hour>
Sayı ile köşeli ayraç arasına boşluk koymazsınız; ancak, aşağıdaki örnekte olduğu gibi gibi f
sabit bir sonek ekleyebilirsiniz.
// The f indicates single-precision floating point.
55.0f<miles/hour>
Böyle bir ek açıklama, değişmez değerin türünü ilkel türünden (örneğinfloat
) veya float<miles/hour>
gibi float<cm>
boyutlandırılmış bir türe değiştirir. birim ek açıklaması <1>
boyutsuz miktarı belirtir ve türü birim parametresi olmayan ilkel türe eşdeğerdir.
Ölçü biriminin türü, köşeli ayraç içinde belirtilen ek birim ek açıklamasıyla birlikte kayan nokta veya imzalı tam sayı türüdür. Bu nedenle, bir dönüştürme türünü (gram) ile g
(kilogram) kg
yazdığınızda, türleri aşağıdaki gibi açıklarsınız.
let convertg2kg (x : float<g>) = x / 1000.0<g/kg>
Ölçü birimleri derleme zamanı birim denetimi için kullanılır ancak çalışma zamanı ortamında kalıcı değildir. Bu nedenle, performansı etkilemez.
Ölçü birimleri yalnızca kayan nokta türlerine değil, herhangi bir türe uygulanabilir; ancak yalnızca kayan nokta türleri, imzalı tam sayı türleri ve ondalık türleri boyutlanmış miktarları destekler. Bu nedenle, yalnızca temel türlerde ve bu temel türleri içeren toplamalarda ölçü birimlerini kullanmak mantıklıdır.
Aşağıdaki örnekte ölçü birimlerinin kullanımı gösterilmektedir.
// Mass, grams.
[<Measure>] type g
// Mass, kilograms.
[<Measure>] type kg
// Weight, pounds.
[<Measure>] type lb
// Distance, meters.
[<Measure>] type m
// Distance, cm
[<Measure>] type cm
// Distance, inches.
[<Measure>] type inch
// Distance, feet
[<Measure>] type ft
// Time, seconds.
[<Measure>] type s
// Force, Newtons.
[<Measure>] type N = kg m / s^2
// Pressure, bar.
[<Measure>] type bar
// Pressure, Pascals
[<Measure>] type Pa = N / m^2
// Volume, milliliters.
[<Measure>] type ml
// Volume, liters.
[<Measure>] type L
// Define conversion constants.
let gramsPerKilogram : float<g kg^-1> = 1000.0<g/kg>
let cmPerMeter : float<cm/m> = 100.0<cm/m>
let cmPerInch : float<cm/inch> = 2.54<cm/inch>
let mlPerCubicCentimeter : float<ml/cm^3> = 1.0<ml/cm^3>
let mlPerLiter : float<ml/L> = 1000.0<ml/L>
// Define conversion functions.
let convertGramsToKilograms (x : float<g>) = x / gramsPerKilogram
let convertCentimetersToInches (x : float<cm>) = x / cmPerInch
Aşağıdaki kod örneği, boyutsuz kayan nokta sayısından boyutlanmış kayan nokta değerine nasıl dönüştürüldüğünü gösterir. Boyutları 1,0'a uygulayarak yalnızca 1,0 ile çarpabilirsiniz. Bunu gibi degreesFahrenheit
bir işleve soyutlayabilirsiniz.
Ayrıca, boyutsuz kayan nokta sayıları bekleyen işlevlere boyutlanmış değerler geçirdiğinizde, işlecini kullanarak birimleri iptal etmeniz veya atamayı float
float
gerçekleştirmeniz gerekir. Bu örnekte, boyutsuz miktarlar beklediğinden bağımsız değişkenler için printf
printf
ölçütü olarak bölersiniz1.0<degC>
.
[<Measure>] type degC // temperature, Celsius/Centigrade
[<Measure>] type degF // temperature, Fahrenheit
let convertCtoF ( temp : float<degC> ) = 9.0<degF> / 5.0<degC> * temp + 32.0<degF>
let convertFtoC ( temp: float<degF> ) = 5.0<degC> / 9.0<degF> * ( temp - 32.0<degF>)
// Define conversion functions from dimensionless floating point values.
let degreesFahrenheit temp = temp * 1.0<degF>
let degreesCelsius temp = temp * 1.0<degC>
printfn "Enter a temperature in degrees Fahrenheit."
let input = System.Console.ReadLine()
let parsedOk, floatValue = System.Double.TryParse(input)
if parsedOk
then
printfn "That temperature in Celsius is %8.2f degrees C." ((convertFtoC (degreesFahrenheit floatValue))/(1.0<degC>))
else
printfn "Error parsing input."
Aşağıdaki örnek oturumda çıkışlar ve bu koda girişler gösterilmektedir.
Enter a temperature in degrees Fahrenheit.
90
That temperature in degrees Celsius is 32.22.
Ölçü Birimlerini Destekleyen Temel Türler
Aşağıdaki tür veya tür kısaltma diğer adları ölçü birimi ek açıklamalarını destekler:
F# diğer adı | CLR Türü |
---|---|
float32 /single |
System.Single |
float /double |
System.Double |
decimal |
System.Decimal |
sbyte /int8 |
System.SByte |
int16 |
System.Int16 |
int /int32 |
System.Int32 |
int64 |
System.Int64 |
byte /uint8 |
System.Byte |
uint16 |
System.UInt16 |
uint /uint32 |
System.UInt32 |
uint64 |
System.UIn64 |
nativeint |
System.IntPtr |
unativeint |
System.UIntPtr |
Örneğin, işaretsiz bir tamsayıya aşağıdaki gibi ek açıklama ekleyebilirsiniz:
[<Measure>]
type days
let better_age = 3u<days>
Bu özelliğe işaretsiz tamsayı türlerinin eklenmesi F# RFC FS-1091'de belgelenmiştir.
Önceden Tanımlanmış Ölçü Birimleri
Ad alanında FSharp.Data.UnitSystems.SI
bir birim kitaplığı kullanılabilir. Si birimlerini hem sembol biçiminde (ölçüm için olduğu gibi m
) UnitSymbols
alt ad alanında hem de alt ad alanında tam adlarında (ölçüm için olduğu gibi meter
) UnitNames
içerir.
Genel Birimleri Kullanma
İlişkili ölçü birimine sahip veriler üzerinde çalışan genel işlevler yazabilirsiniz. Bunu, aşağıdaki kod örneğinde gösterildiği gibi tür parametresi olarak genel bir birimle birlikte bir tür belirterek yaparsınız.
// Distance, meters.
[<Measure>] type m
// Time, seconds.
[<Measure>] type s
let genericSumUnits ( x : float<'u>) (y: float<'u>) = x + y
let v1 = 3.1<m/s>
let v2 = 2.7<m/s>
let x1 = 1.2<m>
let t1 = 1.0<s>
// OK: a function that has unit consistency checking.
let result1 = genericSumUnits v1 v2
// Error reported: mismatched units.
// Uncomment to see error.
// let result2 = genericSumUnits v1 x1
Genel Birimlerle Koleksiyon Türleri Oluşturma
Aşağıdaki kod, genel birimlere sahip tek tek kayan nokta değerlerinden oluşan bir toplama türünün nasıl oluşturulacağını gösterir. Bu, çeşitli birimlerle çalışan tek bir türün oluşturulmasını sağlar. Ayrıca, genel birimler, bir birim kümesine sahip genel bir türün, farklı bir birim kümesine sahip aynı genel türden farklı bir tür olduğundan emin olarak tür güvenliğini korur. Bu tekniğin temeli, özniteliğin Measure
tür parametresine uygulanabilmesidir.
// Distance, meters.
[<Measure>] type m
// Time, seconds.
[<Measure>] type s
// Define a vector together with a measure type parameter.
// Note the attribute applied to the type parameter.
type vector3D<[<Measure>] 'u> = { x : float<'u>; y : float<'u>; z : float<'u>}
// Create instances that have two different measures.
// Create a position vector.
let xvec : vector3D<m> = { x = 0.0<m>; y = 0.0<m>; z = 0.0<m> }
// Create a velocity vector.
let v1vec : vector3D<m/s> = { x = 1.0<m/s>; y = -1.0<m/s>; z = 0.0<m/s> }
Çalışma Zamanında Birimler
Ölçü birimleri statik tür denetimi için kullanılır. Kayan nokta değerleri derlendiğinde ölçü birimleri ortadan kaldırıldığından, birimler çalışma zamanında kaybolur. Bu nedenle, çalışma zamanında birimleri denetlemeye bağlı işlevleri uygulamaya yönelik herhangi bir girişim mümkün değildir. Örneğin, birimleri yazdırmak için bir ToString
işlev uygulamak mümkün değildir.
Dönüşümler
Birimleri olan bir türü (örneğin, float<'u>
) birim içermeyen bir türe dönüştürmek için standart dönüştürme işlevini kullanabilirsiniz. Örneğin, aşağıdaki kodda gösterildiği gibi birimleri olmayan bir float
değere dönüştürmek için kullanabilirsinizfloat
.
[<Measure>]
type cm
let length = 12.0<cm>
let x = float length
Birimsiz değeri birimleri olan bir değere dönüştürmek için, uygun birimlerle ek açıklamalı 1 veya 1,0 değeriyle çarpabilirsiniz. Bununla birlikte, birlikte çalışabilirlik katmanları yazmak için birimsiz değerleri birimlerle değerlere dönüştürmek için kullanabileceğiniz bazı açık işlevler de vardır. Bunlar FSharp.Core.LanguagePrimitives modülünde bulunur . Örneğin, aşağıdaki kodda gösterildiği gibi, bir birimsizden float
öğesine float<cm>
dönüştürmek için FloatWithMeasure kullanın.
open Microsoft.FSharp.Core
let height:float<cm> = LanguagePrimitives.FloatWithMeasure x