使用 Boost.Units 定义百分比
Using Boost.Units to define percentage
我想用Boost.Units实现一个percent
单位,以便无量纲的数量(如比率(可以表示为百分比。我已经成功地实现了质量密度单位之间的转换,但同样不适用于无量纲单位。这是我的代码(假设using namespace boost::units;
(:
//
// gram per milliliter (g mL^-1)
//
namespace my {
struct gram_per_milliliter_base_unit :
base_unit<gram_per_milliliter_base_unit, mass_density_dimension, 1>
{
static std::string name() {return "gram per milliliter";}
static std::string symbol() {return "g mL^-1";}
};
typedef gram_per_milliliter_base_unit::unit_type gram_per_milliliter_unit;
BOOST_UNITS_STATIC_CONSTANT(gram_per_milliliter, gram_per_milliliter_unit);
BOOST_UNITS_STATIC_CONSTANT(grams_per_milliliter, gram_per_milliliter_unit);
}
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(
my::gram_per_milliliter_base_unit, si::mass_density, double, 1.0e3
); // 1 g mL^-1 == 1e3 kg m^-3 (SI unit)
BOOST_UNITS_DEFAULT_CONVERSION(my::gram_per_milliliter_base_unit, si::mass_density);
//
// percentage (%)
//
namespace my {
struct percent_base_unit :
base_unit<percent_base_unit, dimensionless_type, 2>
{
static std::string name() {return "percent";}
static std::string symbol() {return "%";}
};
typedef percent_base_unit::unit_type percent_unit;
BOOST_UNITS_STATIC_CONSTANT(percent, percent_unit);
}
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(
my::percent_base_unit, si::dimensionless, double, 1.0e-2
); // 1 % == 1e-2 (SI dimensionless unit)
BOOST_UNITS_DEFAULT_CONVERSION(my::percent_base_unit, si::dimensionless);
"克/毫升"部分按预期工作:我可以编译此代码(假设using namespace my;
(:
quantity<gram_per_milliliter_unit> q1my(3*grams_per_milliliter);
quantity<si::mass_density> q1si(q1my);
quantity<gram_per_milliliter_unit> q1back(q1si);
但以下内容无法在两次转换上编译:
quantity<percent_unit> q2my(3*percent);
quantity<si::dimensionless> q2si(q2my);
quantity<percent_unit> q2back(q2si);
G++ 输出:no matching function for call to 'conversion_factor(..., ...)'
.
这是否与dimensionless_type
似乎是打字表结束的标记这一事实有关?
任何帮助或建议将不胜感激。谢谢。
这是否与dimensionless_type似乎是打字列表结束的标记这一事实有关?
有点。 dimensionless_type
隐式包含在每个测量系统中,并以相同的方式从中提取,请参阅boost/units/dimensionless_units.hpp
。
在您的"百分比"示例中,想想您的新测量系统将是什么,以及如何根据通常的提升单位规则指定它:
namespace my {
... // define your own unit tag types
typedef make_system</* your system's units with dimensions*/>::type system;
... // unit typedefs, consts, etc.
}
因此,如果你说你的百分比将是无量纲的,但与原来的无量纲不同,你就是在挑战上述概念。因此,您无法在系统中定义 2 个无量纲维度。
任何帮助或建议将不胜感激。
我在这里看到 3 个选项:
覆盖基础数量类型,并在 ctor 中接受百分比或常规数字。见 http://www.boost.org/doc/libs/release/doc/html/boost_units/Examples.html#boost_units.Examples.UDTExample
如果要以百分比显示内容,可以尝试使用自动缩放功能(我自己从未做过,但也有一个例子 - http://www.boost.org/doc/libs/release/doc/html/boost_units/Examples.html#boost_units.Examples.autoscale(。
您可以创建一个特殊的自定义维度"百分比",并显式转换为百分比数量/从百分比数量转换。这可能最接近您的原始意图,但自动转换并不总是会发生,因为该库不是为"无量纲量的维度分析"而设计的。如果您尝试强制系统进行自动转换,您可以看到结果有多难看:
// // percentage (%) // namespace my { struct percent_base_dimension : base_dimension<percent_base_dimension, 1> {}; typedef percent_base_dimension::dimension_type percent_type; struct percent_base_unit : base_unit<percent_base_unit, percent_type, 1> { static std::string name() {return "percent";} static std::string symbol() {return "%";} }; typedef make_system<percent_base_unit>::type system; typedef percent_base_unit::unit_type percent_unit; BOOST_UNITS_STATIC_CONSTANT(percent, percent_unit); } namespace boost { namespace units { template<class T0, class T1> struct conversion_helper<quantity<my::percent_unit, T0>, quantity<si::dimensionless, T1> > { static quantity<si::dimensionless, T1> convert(const quantity<my::percent_unit, T0>& source) { return(quantity<si::dimensionless, T1>::from_value(1e-2 * source.value())); } }; template<class T0, class T1> struct conversion_helper<quantity<si::dimensionless, T0>, quantity<my::percent_unit, T1> > { static quantity<my::percent_unit, T1> convert(const quantity<si::dimensionless, T0>& source) { return(quantity<my::percent_unit, T1>::from_value(1e+2 * source.value())); } }; } } int main() { using namespace my; quantity<percent_unit> q2my(3*percent); //quantity<si::dimensionless> q2si(q2my); //The converter won't be picked up due to an explicit disable_if in quantity.hpp: // typename boost::disable_if<detail::is_dimensionless_system<System2> >::type* = 0 //so we manually force the conversion here: auto conv = conversion_helper<quantity<percent_unit>, quantity<si::dimensionless> >::convert; quantity<si::dimensionless> q2si(conv(q2my)); quantity<percent_unit> q2back(q2si); std::cout << "q2my: " << q2my << std::endl << "q2si: " << q2si << std::endl << "q2back: " << q2back << std::endl ; }
所以手动做是个好主意,比如
namespace my { template<class Y> quantity<si::dimensionless, Y> units(const quantity<percent_unit, Y>& source) { return(quantity<si::dimensionless, Y>::from_value(1e-2 * source.value())); } template<class Y> quantity<percent_unit, Y> percentage(const quantity<si::dimensionless, Y>& source) { return(quantity<percent_unit, Y>::from_value(1e+2 * source.value())); } } int main() { using namespace my; quantity<percent_unit> q2my(3*percent); quantity<si::dimensionless> q2si(my::units(q2my)); quantity<percent_unit> q2back(my::percentage(q2si)); std::cout << "q2my: " << q2my << std::endl << "q2si: " << q2si << std::endl << "q2back: " << q2back << std::endl ; }
或者,更好的是,使用类型检查的好处(所以你在这里只能犯一个转换因子的错误(:
template<class Y> quantity<si::dimensionless, Y> units(const quantity<percent_unit, Y>& source) { return quantity<si::dimensionless, Y>(1e-2 * source / percent); } template<class Y> quantity<percent_unit, Y> percentage(const quantity<si::dimensionless, Y>& source) { return quantity<percent_unit, Y>(1e+2 * source * percent); }
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在命名空间中定义函数还是限定函数
- 此代码是否违反一个定义规则
- 编译C++时未定义的引用
- 不同翻译单元中不可重载的非内联函数定义
- 为什么在定义函数之前先声明它
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- vscode g++链路故障:体系结构x86_64的未定义符号
- 使用 Boost.Units 定义百分比