Does it make sens in C++ to define physics units as separate types and define valid operations between those types?
它是否使c++中的sens将物理单元定义为独立的类型,并在这些类型之间定义有效的操作?
Is there any advantage in introducing a lot of types and a lot of operator overloading instead of using just plain floating point values to represent them?
引入大量类型和操作符重载而不是仅仅使用普通的浮点值来表示它们,这有什么好处吗?
Example:
例子:
class Time{...};
class Length{...};
class Speed{...};
...
Time operator""_s(long double val){...}
Length operator""_m(long double val){...}
...
Speed operator/(const Length&, const Time&){...}
Where Time
, Length
and Speed
can be created only as a return type from different operators?
时间、长度和速度只能作为不同操作符的返回类型创建吗?
9 个解决方案
#1
53
Does it make sens in C++ to define physics units as separate types and define valid operations between those types?
它是否使c++中的sens将物理单元定义为独立的类型,并在这些类型之间定义有效的操作?
Absolutely. The standard Chrono library already does this for time points and durations.
绝对的。标准的Chrono库已经对时间点和持续时间进行了上述操作。
Is there any advantage in introducing a lot of types and a lot of operator overloading instead of using just plain floating point values to represent them?
引入大量类型和操作符重载而不是仅仅使用普通的浮点值来表示它们,这有什么好处吗?
Yes: you can use the type system to catch errors like adding a mass to a distance at compile time, without adding any runtime overhead.
是的:您可以使用类型系统来捕获错误,比如在编译时向距离添加质量,而不添加任何运行时开销。
If you don't feel like defining the types and operators yourself, Boost has a Units library for that.
如果您不想自己定义类型和操作符,Boost提供了一个单元库。
#2
21
I would really recommend boost::units for this. It does all the conversion compile-time and also it gives you a compile time error if you're trying using erroneous dimensions psuedo code example:
我真的推荐boost::这款产品的单元。它执行所有的转换编译时,如果你试图使用错误的维数psuedo代码示例,它还会给你一个编译时错误:
length l1, l2, l3;
area a1 = l1 * l2; // Compiles
area a2 = l1 * l2 * l3; // Compile time error, an area can't be the product of three lengths.
volume v1 = l1 * l2 * l3; // Compiles
#3
13
I've gone down this road. The advantages are all the normal numerous and good advantages of type safety. The disadvantages I've run into:
我沿着这条路走。优点是所有的优点和优点,类型安全。我遇到的缺点:
- You'll want to save off intermediate values in calculations... such as seconds squared. Having these values be a type is somewhat meaningless (seconds^2 obviously isn't a type like
velocity
is). - 您将希望在计算中保存中间值……如秒的平方。这些值是一种有点意义(秒^ 2显然不是一个类型如速度)。
- You'll want to do increasingly complex calculations which will require more and more overloads/operator defines to achieve.
- 您将希望进行越来越复杂的计算,这将需要越来越多的重载/操作符定义来实现。
At the end of the day, it's extremely clean for simple calculations and simple purposes. But when math gets complicated, it's hard to have a typed unit system play nice.
最后,它对于简单的计算和简单的目的来说是非常干净的。但是当数学变得复杂的时候,很难让类型化的单元系统表现得很好。
#4
10
Everyone has mentioned the type-safety guarantees as a plus. Another HUGE plus is the ability to abstract the concept (length) from the units (meter).
每个人都提到了类型安全保证作为一个优点。另一个巨大的优点是能够从单位(米)中抽象出概念(长度)。
So for example, a common issue when dealing with units is to mix SI with metric. When the concepts are abstracted as classes, this is no longer an issue:
例如,在处理单位时,一个常见的问题是将SI和度规混合。当概念抽象为类时,这不再是一个问题:
Length width = Length::fromMeters(2.0);
Length height = Length::fromFeet(6.5);
Area area = width * height; //Area is computed correctly!
cout << "The total area is " << area.toInches() << " inches squared.";
The user of the class doesn't need to know what units the internal-representation uses... at least, as long as there are no severe rounding issues.
类的用户不需要知道内部表示使用的单位是什么……至少,只要没有严重的舍入问题。
I really wish more trigonometry libraries did this with angles, because I always have to look up whether they're expecting degrees or radians...
我真的希望有更多的三角函数库用角度来做这件事,因为我总是要查找它们是期望的角度还是弧度……
#5
4
For those looking for a powerful compile-time type-safe unit library, but are hesitant about dragging in a boost dependency, check out units. The library is implemented as a single .h file with no dependencies, and comes with a project to build unit tests/documentation. It's tested with msvc2013, 2015, and gcc-4.9.2, and should work with later versions of those compilers as well.
对于那些正在寻找强大的编译时类型安全的单元库,但又不愿拖进一个boost依赖项的人,请检查单元。该库实现为一个没有依赖项的.h文件,并附带了一个构建单元测试/文档的项目。它已经通过msvc2013、2015和gcc-4.9.2进行了测试,并且应该也可以使用这些编译器的后续版本。
Full Disclosure: I'm the author of the library
我是图书馆的作者
#6
1
Yes, it makes sense. Not only in physics, but in any discipline. In finance, e.g. interest rates are in units of inverse time intervals (typically express per year). Money has many different units. Converting between them can only be done with a cross-rate, has dimensions of one currency divided by another. Interest payments, dividend payments, principal payments, etc. ordinarily occur at a frequency.
是的,它是有意义的。不仅在物理学上,而且在任何学科上。在金融领域,例如利率是以逆时间间隔为单位的(通常是每年表示一次)。钱有许多不同的单位。它们之间的转换只能通过交叉汇率来完成,它的维度是一种货币除以另一种货币。利息支付、股息支付、本金支付等通常发生在一个频率上。
It can prevent multiplying two values and ending up with an illegal value. It can prevent summing dollars and euros, etc.
它可以防止两个值相乘,最终得到一个非法值。它可以防止美元和欧元等的总和。
#7
1
I'm not saying you're wrong to do so, but we've gone overboard with that on the project I'm working on and frankly I doubt its benefits outweigh its hassle. Particularly if you're on a team, good variable naming (just spell the darn things out), code reviews, and unit testing will prevent any problems. On the other hand, if you can use Boost, units might be something to check into (I haven't).
我并不是说你这样做是错误的,但是我们在我正在做的项目中已经做得太过火了,坦白地说,我怀疑它的好处大于麻烦。尤其是在团队中,好的变量命名(只需拼写出讨厌的东西)、代码检查和单元测试将防止任何问题。另一方面,如果您可以使用Boost,那么单元可能是需要检查的内容(我没有)。
#8
1
To check for type safety, you can use a dedicated library.
要检查类型安全性,可以使用专用库。
The most wiedly use is boost::units, it works perfertly with no execution time overhead, a lot of features. If this library theoritically solve your problem. From a more practical point of vew, the interface is so awkward and badly documented that you may have problems. Morever the compilation time increase drastically with the number of dimensions, so clearly check that you can compile in a reasonable time a large project before using it.
最广泛使用的是boost::单元,它工作得很好,没有执行时间开销,有很多特性。如果这个库从理论上解决了你的问题。从vew的一个更实际的角度来看,这个接口是如此的笨拙和糟糕,以至于您可能会遇到问题。编译时间会随着维度的增加而急剧增加,所以要清楚地检查在使用它之前,您可以在合理的时间内编译一个大型项目。
doc : http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
医生:http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
An alternative is to use unit_lite. There are less features than the boost library but the compilation is faster, the interface simpler and errors messages are readables. This lib requires C++11.
另一种选择是使用unit_lite。与boost库相比,它的特性更少,但编译速度更快,界面更简单,错误消息是可读的。这种*需要c++ 11。
code : https://github.com/pierreblavy2/unit_lite
代码:https://github.com/pierreblavy2/unit_lite
The link to the doc is in the github description (I'm not allowed to post more than 2 links here !!!).
到doc的链接在github描述中(我不允许在这里发布超过两个链接!!)
#9
1
I gave a tutorial presentation at CPPcon 2015 on the Boost.Units library. It's a powerful library that every scientific application should be using. But it's hard to use due to poor documentation. Hopefully my tutorial helps with this. You can find the slides/code here:
我在CPPcon 2015上做了一个关于Boost的教程演示。单元库。它是一个强大的库,每个科学应用都应该使用它。但是由于文档不完善,所以很难使用。希望我的教程能帮上忙。你可以在这里找到幻灯片/代码:
#1
53
Does it make sens in C++ to define physics units as separate types and define valid operations between those types?
它是否使c++中的sens将物理单元定义为独立的类型,并在这些类型之间定义有效的操作?
Absolutely. The standard Chrono library already does this for time points and durations.
绝对的。标准的Chrono库已经对时间点和持续时间进行了上述操作。
Is there any advantage in introducing a lot of types and a lot of operator overloading instead of using just plain floating point values to represent them?
引入大量类型和操作符重载而不是仅仅使用普通的浮点值来表示它们,这有什么好处吗?
Yes: you can use the type system to catch errors like adding a mass to a distance at compile time, without adding any runtime overhead.
是的:您可以使用类型系统来捕获错误,比如在编译时向距离添加质量,而不添加任何运行时开销。
If you don't feel like defining the types and operators yourself, Boost has a Units library for that.
如果您不想自己定义类型和操作符,Boost提供了一个单元库。
#2
21
I would really recommend boost::units for this. It does all the conversion compile-time and also it gives you a compile time error if you're trying using erroneous dimensions psuedo code example:
我真的推荐boost::这款产品的单元。它执行所有的转换编译时,如果你试图使用错误的维数psuedo代码示例,它还会给你一个编译时错误:
length l1, l2, l3;
area a1 = l1 * l2; // Compiles
area a2 = l1 * l2 * l3; // Compile time error, an area can't be the product of three lengths.
volume v1 = l1 * l2 * l3; // Compiles
#3
13
I've gone down this road. The advantages are all the normal numerous and good advantages of type safety. The disadvantages I've run into:
我沿着这条路走。优点是所有的优点和优点,类型安全。我遇到的缺点:
- You'll want to save off intermediate values in calculations... such as seconds squared. Having these values be a type is somewhat meaningless (seconds^2 obviously isn't a type like
velocity
is). - 您将希望在计算中保存中间值……如秒的平方。这些值是一种有点意义(秒^ 2显然不是一个类型如速度)。
- You'll want to do increasingly complex calculations which will require more and more overloads/operator defines to achieve.
- 您将希望进行越来越复杂的计算,这将需要越来越多的重载/操作符定义来实现。
At the end of the day, it's extremely clean for simple calculations and simple purposes. But when math gets complicated, it's hard to have a typed unit system play nice.
最后,它对于简单的计算和简单的目的来说是非常干净的。但是当数学变得复杂的时候,很难让类型化的单元系统表现得很好。
#4
10
Everyone has mentioned the type-safety guarantees as a plus. Another HUGE plus is the ability to abstract the concept (length) from the units (meter).
每个人都提到了类型安全保证作为一个优点。另一个巨大的优点是能够从单位(米)中抽象出概念(长度)。
So for example, a common issue when dealing with units is to mix SI with metric. When the concepts are abstracted as classes, this is no longer an issue:
例如,在处理单位时,一个常见的问题是将SI和度规混合。当概念抽象为类时,这不再是一个问题:
Length width = Length::fromMeters(2.0);
Length height = Length::fromFeet(6.5);
Area area = width * height; //Area is computed correctly!
cout << "The total area is " << area.toInches() << " inches squared.";
The user of the class doesn't need to know what units the internal-representation uses... at least, as long as there are no severe rounding issues.
类的用户不需要知道内部表示使用的单位是什么……至少,只要没有严重的舍入问题。
I really wish more trigonometry libraries did this with angles, because I always have to look up whether they're expecting degrees or radians...
我真的希望有更多的三角函数库用角度来做这件事,因为我总是要查找它们是期望的角度还是弧度……
#5
4
For those looking for a powerful compile-time type-safe unit library, but are hesitant about dragging in a boost dependency, check out units. The library is implemented as a single .h file with no dependencies, and comes with a project to build unit tests/documentation. It's tested with msvc2013, 2015, and gcc-4.9.2, and should work with later versions of those compilers as well.
对于那些正在寻找强大的编译时类型安全的单元库,但又不愿拖进一个boost依赖项的人,请检查单元。该库实现为一个没有依赖项的.h文件,并附带了一个构建单元测试/文档的项目。它已经通过msvc2013、2015和gcc-4.9.2进行了测试,并且应该也可以使用这些编译器的后续版本。
Full Disclosure: I'm the author of the library
我是图书馆的作者
#6
1
Yes, it makes sense. Not only in physics, but in any discipline. In finance, e.g. interest rates are in units of inverse time intervals (typically express per year). Money has many different units. Converting between them can only be done with a cross-rate, has dimensions of one currency divided by another. Interest payments, dividend payments, principal payments, etc. ordinarily occur at a frequency.
是的,它是有意义的。不仅在物理学上,而且在任何学科上。在金融领域,例如利率是以逆时间间隔为单位的(通常是每年表示一次)。钱有许多不同的单位。它们之间的转换只能通过交叉汇率来完成,它的维度是一种货币除以另一种货币。利息支付、股息支付、本金支付等通常发生在一个频率上。
It can prevent multiplying two values and ending up with an illegal value. It can prevent summing dollars and euros, etc.
它可以防止两个值相乘,最终得到一个非法值。它可以防止美元和欧元等的总和。
#7
1
I'm not saying you're wrong to do so, but we've gone overboard with that on the project I'm working on and frankly I doubt its benefits outweigh its hassle. Particularly if you're on a team, good variable naming (just spell the darn things out), code reviews, and unit testing will prevent any problems. On the other hand, if you can use Boost, units might be something to check into (I haven't).
我并不是说你这样做是错误的,但是我们在我正在做的项目中已经做得太过火了,坦白地说,我怀疑它的好处大于麻烦。尤其是在团队中,好的变量命名(只需拼写出讨厌的东西)、代码检查和单元测试将防止任何问题。另一方面,如果您可以使用Boost,那么单元可能是需要检查的内容(我没有)。
#8
1
To check for type safety, you can use a dedicated library.
要检查类型安全性,可以使用专用库。
The most wiedly use is boost::units, it works perfertly with no execution time overhead, a lot of features. If this library theoritically solve your problem. From a more practical point of vew, the interface is so awkward and badly documented that you may have problems. Morever the compilation time increase drastically with the number of dimensions, so clearly check that you can compile in a reasonable time a large project before using it.
最广泛使用的是boost::单元,它工作得很好,没有执行时间开销,有很多特性。如果这个库从理论上解决了你的问题。从vew的一个更实际的角度来看,这个接口是如此的笨拙和糟糕,以至于您可能会遇到问题。编译时间会随着维度的增加而急剧增加,所以要清楚地检查在使用它之前,您可以在合理的时间内编译一个大型项目。
doc : http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
医生:http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
An alternative is to use unit_lite. There are less features than the boost library but the compilation is faster, the interface simpler and errors messages are readables. This lib requires C++11.
另一种选择是使用unit_lite。与boost库相比,它的特性更少,但编译速度更快,界面更简单,错误消息是可读的。这种*需要c++ 11。
code : https://github.com/pierreblavy2/unit_lite
代码:https://github.com/pierreblavy2/unit_lite
The link to the doc is in the github description (I'm not allowed to post more than 2 links here !!!).
到doc的链接在github描述中(我不允许在这里发布超过两个链接!!)
#9
1
I gave a tutorial presentation at CPPcon 2015 on the Boost.Units library. It's a powerful library that every scientific application should be using. But it's hard to use due to poor documentation. Hopefully my tutorial helps with this. You can find the slides/code here:
我在CPPcon 2015上做了一个关于Boost的教程演示。单元库。它是一个强大的库,每个科学应用都应该使用它。但是由于文档不完善,所以很难使用。希望我的教程能帮上忙。你可以在这里找到幻灯片/代码: