单位转换的良好数据结构?

发布于 2024-09-08 13:44:56 字数 1431 浏览 12 评论 0原文

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

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

发布评论

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

评论(6

燃情 2024-09-15 13:44:56

我将从一个哈希表(或持久查找表 - 您选择如何实现)开始,它在您想要放入的尽可能多的对之间进行单位转换。如果您放入每个可能的对,那么这就是您的蛮力方法。

如果您只有部分对,则可以在必须找到组合的对中进行搜索。例如,假设我的哈希表中有这两个条目:

Feet|Inches|1/12
Inches|Centimeters|2.54

现在,如果我想将英尺转换为厘米,我有一个简单的图形搜索:顶点是英尺、英寸和厘米,边是 1/12 和 2.54 转换因素。本例中的解是两条边 1/12, 2.54(当然是通过乘法合并的)。如果您愿意,您可以对图形参数进行更深入的研究。

另一种方法可能是应用溯因推理 - 为此查看有关代数问题求解器的人工智能文本...

编辑:解决复合单位

简化问题:将“英亩”转换为“米^2”

在这种情况下,关键是要理解我们正在谈论长度单位,那么为什么我们不在表中插入一个新列来表示单位类型,可以是“长度”或“面积”。即使在早期的情况下,这也将有助于提高性能,因为它为您提供了一个简单的列来减少搜索空间。

现在的技巧是理解长度^2 = 面积。为什么不添加另一个存储此元数据的查找:

Area|Length|Length|*

我们将其与主要单位表结合起来:

Meters|Feet|3.28|Length
Acres|Feet^2|43560|Area

因此算法如下:

  • 解决方案是 m^2,即 m * m,即长度 * 长度。
  • 输入单位为英亩,即面积。
  • 在元表中搜索 m,并找到长度 * 长度映射。请注意,在更复杂的示例中,可能存在多个有效映射。
  • 将转换 Acres->Feet^2 附加到解决方案。
  • 对 Feet->M 执行原始图形搜索。

请注意:

  • 该算法不知道是否使用面积或长度作为工作的基本域。您可以向它提供提示,或者让它搜索两个空间。
  • 元表有点暴力。
  • 如果您开始混合类型(例如电阻 = 电压/电流)或做一些非常丑陋的事情并混合单位系统(例如 FooArea = 米 * 英尺),元表将需要变得更智能。

I would start with a hashtable (or persisted lookup table - your choice how you implement) that carries unit conversions between as many pairs as you care to put in. If you put in every possible pair, then this is your brute force approach.

If you have only partial pairs, you can then do a search across the pairs you do have to find a combination. For example, let's say I have these two entries in my hashtable:

Feet|Inches|1/12
Inches|Centimeters|2.54

Now if I want to convert feet to centimeters, I have a simple graph search: vertices are Feet, Inches, and Centimeters, and edges are the 1/12 and 2.54 conversion factors. The solution in this case is the two edges 1/12, 2.54 (combined via multiplication, of course). You can get fancier with the graph parameters if you want to.

Another approach might be applying abductive reasoning - look into AI texts about algebraic problem solvers for this...

Edit: Addressing Compound Units

Simplified problem: convert "Acres" to "Meters^2"

In this case, the keys are understanding that we are talking about units of length, so why don't we insert a new column into the table for unit type, which can be "length" or "area". This will help performance even in the earlier cases as it gives you an easy column to pare down your search space.

Now the trick is to understand that length^2 = area. Why not add another lookup that stores this metadata:

Area|Length|Length|*

We couple this with the primary units table:

Meters|Feet|3.28|Length
Acres|Feet^2|43560|Area

So the algorithm goes:

  • Solution is m^2, which is m * m, which is a length * length.
  • Input is acres, which is an area.
  • Search the meta table for m, and find the length * length mapping. Note that in more complex examples there may be more than one valid mapping.
  • Append to the solution a conversion Acres->Feet^2.
  • Perform the original graph search for Feet->M.

Note that:

  • The algorithm won't know whether to use area or length as the basic domain in which to work. You can provide it hints, or let it search both spaces.
  • The meta table gets a little brute-force-ish.
  • The meta table will need to get smarter if you start mixing types (e.g. Resistance = Voltage / Current) or doing something really ugly and mixing unit systems (e.g. a FooArea = Meters * Feet).
原谅我要高飞 2024-09-15 13:44:56

无论您选择什么结构,您的选择很可能取决于您的首选实现(OO?功能?DBMS 表?)我认为您需要确定单元本身的结构。

例如,1000 公里/小时的测量值有几个组成部分:

  • 标量大小 1000;
  • 前缀,在本例中为 kilo;以及
  • 维度,在本例中为 LT^(-1),即长度除以时间。

使用单位进行测量建模至少需要捕获这种复杂性。

正如已经建议的那样,您应该确定要使用的基本单位集是什么,SI 基本单位会立即建议自己。然后,您的建模单元的数据结构将根据这些基本单元进行定义。因此,您可以定义一个表(此处考虑 RDBMS,但可以轻松转换为您首选的实现),其中包含以下条目:

unit name      dimension                 conversion to base

foot           Length                    0.3048
gallon(UK)     Length^3                  4.546092 x 10^(-3)
kilowatt-hour  Mass.Length^2.Time^(-2)   3.6 x 10^6

等等。您还需要一个表来将前缀(千、纳、兆、米比等)转换为乘数,以及每个尺寸的基本单位表(即米是长度、秒的基本单位)时间等)。您还必须处理诸如“英尺”之类的单位,它们只是其他单位的同义词。

当然,尺寸的目的是确保您的转换和其他操作(例如将 2 英尺 添加到 3.5 米)相称。

并且,为了进一步阅读,我建议 Cardarelli 的这本书

编辑以回应评论...

我试图摆脱建议(特定于实现的)解决方案,所以我会多胡说八道。复合单位,例如千瓦时,确实会带来问题。一种方法是使用多个单位表达式(例如千瓦和小时)以及组合它们的规则(在本例中为乘法)来标记测量值> 我可以看到这很快就会变得非常棘手。最好将有效的单元集限制为应用程序域中最常见的单元。

至于处理混合单位的测量,定义单位维度的目的是提供一些方法来确保只有合理的操作才能应用于单位测量。因此,明智的做法是将两个长度 (L+L) 加在一起,而不是长度 (L) 和体积 (L^3)。另一方面,明智的做法是用体积除以长度(得到面积 (L^2))。由应用程序来确定每平方米千瓦时等奇怪单位是否有效。

最后,我链接到的书确实列举了所有可能性,我想大多数带有单位的明智应用程序只会实现一个选择。

Whatever structure you choose, and your choice may well be directed by your preferred implementation (OO ? functional ? DBMS table ?) I think you need to identify the structure of units themselves.

For example a measurement of 1000km/hr has several components:

  • a scalar magnitude, 1000;
  • a prefix, in this case kilo; and
  • a dimension, in this case L.T^(-1), that is, length divided by time.

Your modelling of measurements with units needs to capture at least this complexity.

As has already been suggested, you should establish what the base set of units you are going to use are, and the SI base units immediately suggest themselves. Your data structure(s) for modelling units would then be defined in terms of those base units. You might therefore define a table (thinking RDBMS here, but easily translatable into your preferred implementation) with entries such as:

unit name      dimension                 conversion to base

foot           Length                    0.3048
gallon(UK)     Length^3                  4.546092 x 10^(-3)
kilowatt-hour  Mass.Length^2.Time^(-2)   3.6 x 10^6

and so forth. You'll also need a table to translate prefixes (kilo-, nano-, mega-, mibi- etc) into multiplying factors, and a table of base units for each of the dimensions (ie meter is the base unit for Length, second for Time, etc). You'll also have to cope with units such as feet which are simply synonyms for other units.

The purpose of dimension is, of course, to ensure that your conversions and other operations (such as adding 2 feet to 3.5 metres) are commensurate.

And, for further reading, I suggest this book by Cardarelli.

EDIT in response to comments ...

I'm trying to veer away from suggesting (implementation-specific) solutions so I'll waffle a bit more. Compound units, such as kilowatt-hours, do pose a problem. One approach would be to tag measurements with multiple unit-expressions, such as kilowatt and hour, and a rule for combining them, in this case multiplication I could see this getting quite hairy quite quickly. It might be better to restrict the valid set of units to the most common ones in the domain of the application.

As to dealing with measurements in mixed units, well the purpose of defining the Dimension of a unit is to provide some means to ensure that only sensible operations can be applied to measurements-with-units. So, it's sensible to add two lengths (L+L) together, but not a length (L) and a volume (L^3). On the other hand it is sensible to divide a volume by a length (to get an area (L^2)). And it's kind of up to the application to determine if strange units such as kilowatt-hours per square metre are valid.

Finally, the book I link to does enumerate all the possibilities, I guess most sensible applications with units will implement only a selection.

欲拥i 2024-09-15 13:44:56

我首先为每个数量选择一个标准单位(例如,长度为米,力为牛顿等),然后将所有转换系数存储到该单位的表格中,

然后从几天到几小时,例如,您发现每天秒数和每小时秒数的换算系数,然后将它们相除即可找到答案。

为了避免歧义,每个单位都可以与它测量的所有数量类型相关联,并且为了确定要进行哪种转换,您将取这两组类型的交集(如果您剩下 0 个或多个类型,则会吐出一个错误)

I would start by choosing a standard unit for every quantity(eg. meters for length, newtons for force, etc) and then storing all the conversion factors to that unit in a table

then to go from days to hours, for example, you find the conversion factors for seconds per day and seconds per hour and divide them to find the answer.

for ambiguities, each unit could be associated with all the types of quantities it measures, and to determine which conversion to do, you would take the intersection of those two sets of types(and if you're left with 0 or more than one you would spit out an error)

断爱 2024-09-15 13:44:56

我假设您希望以某种三元组 (fstUnit, sndUnit, multiplier) 保存有关转换的数据。

对于单个单位换算:
使用O(1)中的一些哈希函数将单位结构更改为数字,然后将所有乘数放入一个矩阵中(您只需记住右上部分,因为反射是相同,但相反)。

对于复杂的情况:
示例 1. m/s 到 km/h。您检查矩阵中的 (m,km),然后检查 (s,h),然后将结果相乘。
示例 2. m^3 到 km^3。检查 (m,km) 并取三次方。

当然,当类型不匹配(例如字段和体积)时,会出现一些错误。

I assume that you want to hold the data about conversion in some kind of triples (fstUnit, sndUnit, multiplier).

For single unit conversions:
Use some hash functions in O(1) to change the unit stucture to a number, and then put all multipliers in a matrix (you only have to remember the upper-right part, because the reflection is the same, but inversed).

For complex cases:
Example 1. m/s to km/h. You check (m,km) in the matrix, then the (s,h), then multiply the results.
Example 2. m^3 to km^3. You check (m,km) and take it to the third power.

Of course some errors, when types don't match like field and volume.

满意归宿 2024-09-15 13:44:56

您可以为单位创建一个类,它采用所有基本单位的转换系数和指数(我建议为此使用公制单位,这使您的生活更轻松)。例如,在伪 Java 中:


public class Unit {
   public Unit(double factor, int meterExp, int secondExp, int kilogrammExp ... [other base units]) {
     ...
   }
}

//you need the speed in km/h (1 m/s is 3.6 km/h):
Unit kmPerH = new Unit(1 / 3.6, 1, -1, 0, ...)

You can make a class for Units that takes the conversion factor and the exponents of all basic units (I'd suggest to use metric units for this, that makes your life easier). E.g. in Pseudo-Java:


public class Unit {
   public Unit(double factor, int meterExp, int secondExp, int kilogrammExp ... [other base units]) {
     ...
   }
}

//you need the speed in km/h (1 m/s is 3.6 km/h):
Unit kmPerH = new Unit(1 / 3.6, 1, -1, 0, ...)

忆沫 2024-09-15 13:44:56

我将有一个包含这些字段的表:

conversionID
fromUnit
toUnit
multiplier

无论您需要多少行来存储您想要支持的所有转换

如果您想支持多步骤过程(华氏度到摄氏度),您需要一个一对一的与单位表有很多关系,例如转换步骤,其中包含以下字段:

conversionID
sequence
operator
value

如果您想存储一组转换但支持多步转换,例如存储

Feet|Inches|1/12
Inches|Centimeters|2.54

和支持从英尺到厘米的转换,我会将转换计划存储在另一个表中,就像

conversionPlanID
startUnits
endUnits
via

你的行看起来像

1 | feet | centimeters | inches

I would have a table with these fields:

conversionID
fromUnit
toUnit
multiplier

and however many rows you need to store all the conversions you want to support

If you want to support a multi-step process (degrees F to C), you'd need a one-to-many relationship with the units table, say called conversionStep, with fields like

conversionID
sequence
operator
value

If you want to store one set of conversions but support multi-step conversions, like storing

Feet|Inches|1/12
Inches|Centimeters|2.54

and supporting converting from Feet to Centimeters, I would store a conversion plan in another table, like

conversionPlanID
startUnits
endUnits
via

your row would look like

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