保留编程中的计算单位

发布于 2024-10-06 01:12:58 字数 1615 浏览 10 评论 0原文

我想知道是否有任何甜蜜的语言为“英尺”与“英寸”或“厘米”等提供某种抽象。我正在考虑在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:有什么聪明的方法可以在编程中保留单位吗?是否有聪明的方法来命名方法/例程,以便我可以轻松理解我要添加和减去的内容等?

I was wondering if there are any sweet languages that offer some sort of abstraction for "feet" vs "inches" or "cm" etc. I was considering doing something like the following in Java:

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

and be able to get something like

17.7292 meters as the result.

One possible approach is, when making a new value, immediately convert it to a "base" unit, like meters or something, so you can add them easily.

However, I would much rather have the ability to preserve units, so that something like

u(799.95555).feet() - u(76).feet() 

returns

723.95555 feet

and not

243.826452 meters - 23.1648 meters = 220.661652 meters

//220.661652 meters to feet returns 723.955551 feet 

Since this problem seems like it would be really common, is there any framework or even a programming language that exists that handles this elegantly?

I suppose I can just add the units as they are in my methods, adding matching units together and only converting in order to +-*/ [add/subtract/multiply/divide] when they are requested, which is great for adding and subtracting:

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

//total length is 1.91948 m

if I add this to an object B with values

//B
{
    this.inches = 0.8;
    this.meters = 2;
}

//total length is 2.02032 m

and I get a new object that is

{
    this.inches = 37;
    this.meters = 3;
}

//total length is 3.9398 meters

which is totally awesome, I can convert it whenever I want no problem. But operations such as multiplication would fail ...

//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.

So all I really wanted to show with that example was that

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

And I'm pretty sure this means one has to convert to a common unit if they want to multiply or divide.

The example was mostly to discourage the reflexive answer, that you add or subtract them piece-wise before converting at the last moment, since * and / will fail.

tl;dr: Are there any clever ways to preserve units in programming? Are there clever ways to name methods/routines such that it's easy for me to understand what I'm adding and subtracting, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

葬花如无物 2024-10-13 01:12:59

我确实知道有这样一种语言,尽管我自己没有使用过它。
它被称为Frink

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

I know for a fact there is such a language, although I haven't used it myself.
It's called Frink.

It not only allows you to mix different units for the same dimension but also operate on several different physical measurements. The sample calculations on its site are a fun read. I particular like the Superman bit.

妖妓 2024-10-13 01:12:59

F# 提供对度量单位的语言支持。

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

F# has language support for units of measure.

EDIT: See also How do F# Units of Measure work

狼性发作 2024-10-13 01:12:59

许多函数式语言允许为这种单元保存创建类型。在 Haskell 中:

-- 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 会提供类似的功能?

Many functional languages allow creating types for this sort of unit preservation. In Haskell:

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

Now each unit is its own type, and you can only perform operations on values of the same type:

*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>

Now you can create a conversion type class to convert to and from any measurement types

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

Now we can freely convert between types:

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

Of course, packages to do this sort of thing are available in Haskell.

Since you're using Java already, maybe Scala or Clojure would offer similar capabilities?

魂牵梦绕锁你心扉 2024-10-13 01:12:59

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

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

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

货币是单位吗ETC...

I have done a lot of work with Units and there isn't anything comprehensive. You can find a lot of partial utilities (I think there are some distributed with UNIXes). NIST was developing a units markup language but it's been at least a decade cooking.

To do this properly needs an ontology in which the units are defined and the rules for conversion. You also have to deal with prefixes.

If you stick with physical science (SI units) there are 7 (possibly 8) base unit-types and 22 named derived quantities. But there are an also infinote number of ways they can be combined. For example the rate of change of acceleration is called "jerk" by some. In principle you could have an indefinite number of derivatives.

Are currencies units? etc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文