保留用于编程的计算单位

时间:2010-11-30 22:53:46

标签: naming-conventions units-of-measurement

我想知道是否有任何甜言蜜语为“英尺”与“英寸”或“厘米”等提供某种抽象。我正在考虑在Java中做类似以下的事情:

u(56).feet() + u(26).inches()

并且能够获得类似

的内容 结果为17.7292米。

一种可能的方法是,在制作新值时,立即将其转换为“基础”单位,如米或其他东西,这样您就可以轻松添加它们。

但是,我宁愿有能力保留单位,所以像

这样的东西
u(799.95555).feet() - u(76).feet() 

返回

723.95555 feet

而不是

243.826452 meters - 23.1648 meters = 220.661652 meters

//220.661652 meters to feet returns 723.955551 feet 

由于这个问题似乎很常见,是否存在任何框架甚至是一种优雅处理此问题的编程语言?

我想我可以在我的方法中添加单位,将匹配单位添加到一起,只在需要时转换为+-*/ [加/减/乘/除],这很好用于加减:

//A
{
    this.inches = 36.2;
    this.meters = 1;
}

//total length is 1.91948 m

如果我将其添加到具有值

的对象B中
//B
{
    this.inches = 0.8;
    this.meters = 2;
}

//total length is 2.02032 m

我得到一个

的新对象
{
    this.inches = 37;
    this.meters = 3;
}

//total length is 3.9398 meters

这非常棒,每当我想要没问题时我都可以转换它。但乘法等操作会失败......

//A * B = 3.87796383 m^2
{
    this.inches = 28.96;
    this.meters = 2;
}

// ...but multiplying piece-wise and then adding
// gives you 2.01868383 m^2, assuming you make 2m*1m give you 2 m^2.

所以我真的想用这个例子展示的是那个

( A1 + A2 ) * ( Z1 + Z2 ) is not ( A1 * Z1 ) + ( A2 * Z2 )

而且我很确定这意味着如果他们想要乘法或除法,就必须转换为公共单位。

这个例子主要是为了阻止反身回答,你在最后一刻转换之前逐个加或减它们,因为*/会失败。

tl; dr:在编程中是否有任何聪明的方法来保留单位?有没有聪明的方法来命名方法/例程,这样我很容易理解我正在添加和减去的内容等等?

5 个答案:

答案 0 :(得分:5)

我知道有这样一种语言,虽然我自己没有用过它 它被称为Frink

它不仅允许您为同一尺寸混合不同的单位,还可以在几种不同的物理测量上进行操作。其网站上的sample calculations是一个有趣的阅读材料。我特别喜欢Superman位。

答案 1 :(得分:2)

答案 2 :(得分:2)

许多函数式语言允许为这种单元保存创建类型。在哈斯克尔:

-- you need GeneralizedNewtypeDeriving to derive Num
newtype Feet = Feet {unFeet :: Float} deriving (Eq, Show, Num)
newtype Meters = Meters {unMeters :: Float} deriving (Eq, Show, Num)

现在每个单位都是自己的类型,您只能对相同类型的值执行操作:

*Main> let a1 = 1 :: Feet
*Main> let a2 = 2 :: Feet
*Main> let a3 = 3 :: Meters
*Main> a1+a2
Feet 3.0
*Main> a1+a3

<interactive>:1:3:
    Couldn't match expected type `Feet' against inferred type `Meters'
    In the second argument of `(+)', namely `a3'
    In the expression: a1 + a3
    In the definition of `it': it = a1 + a3
*Main>

现在,您可以创建转换类型类以转换为任何测量类型

class LengthMeasure unit where
  untype :: unit -> Float
  toFeet :: unit -> Feet
  toFeet = Feet . (* 3.2808) . untype . toMeters
  toMeters :: unit -> Meters
  toMeters = Meters . (* 0.3048) . untype . toFeet

instance LengthMeasure Feet where
  untype = unFeet
  toFeet = id

instance LengthMeasure Meters where
  untype = unMeters
  toMeters = id

现在我们可以在类型之间自由转换:

*Main> a1+toFeet a3
Feet {unFeet = 10.842401}

当然,在Haskell中执行此类操作的包是available

既然你已经在使用Java了,那么Scala或Clojure可能会提供类似的功能吗?

答案 3 :(得分:1)

答案 4 :(得分:0)

我在单位做了很多工作,没有什么全面的。你可以找到很多部分实用程序(我认为有一些分布式UNIX)。 NIST正在开发一种单位标记语言,但它已经烹饪至少十年了。

要正确地执行此操作,需要一个本体,其中定义了单位和转换规则。你还必须处理前缀。

如果你坚持物理科学(SI单位),有7个(可能是8个)基本单位类型和22个命名派生数量。但是,还有一些无限的方式可以合并。例如,加速度的变化率被一些人称为“加速度”。原则上你可以有无限数量的衍生物。

是货币单位吗?等...