6

我想知道是否有任何甜蜜的语言为“英尺”与“英寸”或“厘米”等提供某种抽象。我正在考虑在 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 

由于这个问题看起来很常见,是否存在任何框架甚至编程语言可以优雅地处理这个问题?

我想我可以在我的方法中添加单位,将匹配的单位添加在一起,并且仅在+-*/请求时转换为 [add/subtract/multiply/divide],这对于加减法非常有用:

//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:有什么聪明的方法可以在编程中保留单位吗?是否有聪明的方法来命名方法/例程,以便我很容易理解我正在添加和减去的内容等?

4

5 回答 5

6

我知道事实上有这样一种语言,虽然我自己没有使用过。
它被称为弗林克

它不仅允许您为相同的维度混合不同的单位,而且还可以对几个不同的物理测量值进行操作。其网站上的示例计算读起来很有趣。我特别喜欢超人位。

于 2010-11-30T23:10:22.723 回答
3

F# 具有对度量单位的语言支持。

编辑:另请参阅F# 度量单位如何工作

于 2010-11-30T23:11:08.823 回答
3

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

-- 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中提供了执行此类操作的包。

既然您已经在使用 Java,也许 Scala 或 Clojure 会提供类似的功能?

于 2010-11-30T23:16:46.393 回答
1

JSR-275 可能相关http://code.google.com/p/unitsofmeasure/

请参阅应该使用哪个 jsr-275 单元实现?

于 2010-11-30T22:56:11.203 回答
0

我在 Units 上做了很多工作,但没有什么全面的。您可以找到很多部分实用程序(我认为有一些随 UNIXes 一起分发)。NIST 正在开发一种单位标记语言,但它至少已经酝酿了十年。

要正确地做到这一点,需要一个本体,其中定义了单位和转换规则。您还必须处理前缀。

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

货币是单位吗?ETC...

于 2010-11-30T22:58:54.270 回答