数字类型介于0和1之间
Number type between 0 and 1
有没有一种自然的方法可以定义0和1之间的数字类型?本质上,一个人可以用double做任何事情,问题是我应该在一些函数中定义一些绑定检查,我有一个(可能很愚蠢)想法,把绑定检查外包给一个类,比如
class Probability {
// the value of the Probability
double val;
Probability(double val):value(val){
// freak out if val > 1 or val < 0
//...
//
};
// operators such as
Probability operator + (Probability const & a, Probability const & b){
double result a.val + b.val;
if ((result > 1) || (result < 0)){
// freak out
result = 0
}
return result;
}
// ...
//
}
这种方法的问题可能是它减慢了每次操作的速度。有没有更快的绑定检查方法?我也想知道如何处理上面代码中的"反常"部分。
您可以使用类Probability
来强制执行边界,在内部存储一个double。如果希望P(0.75) + P(0.5) - P(0.6)
之类的操作起作用,可以让操作符返回一个不进行边界检查的代理对象。这个代理对象将有一个到Probability
的转换运算符,Probability
构造函数将检查边界。如果您只直接使用Probability
类型,并允许形式为ProbabilityResultProxy
的临时性,那么您将获得所需的行为。
下面的示例概述了这种方法。很明显,在实际实现中缺少了很多您想要的东西,但我想专注于一个特定的解决方案,而不是提供一个完整的类。
实例:
#include <iostream>
class Probability {
public:
Probability(double value) {
if (value < 0 || value > 1) throw std::runtime_error("Invalid probability");
value_ = value;
}
double value() const { return value_; }
private:
double value_;
};
class ProbabilityResultProxy {
public:
explicit ProbabilityResultProxy(double p) : value_(p) {}
double value() const { return value_; }
operator Probability() {
return Probability(value_);
}
private:
double value_;
};
ProbabilityResultProxy operator+(const Probability& lhs, const Probability& rhs) {
return ProbabilityResultProxy(lhs.value() + rhs.value());
}
ProbabilityResultProxy operator+(const ProbabilityResultProxy& lhs, const Probability& rhs) {
return ProbabilityResultProxy(lhs.value() + rhs.value());
}
ProbabilityResultProxy operator+(const Probability& lhs, const ProbabilityResultProxy& rhs) {
return ProbabilityResultProxy(lhs.value() + rhs.value());
}
ProbabilityResultProxy operator+(const ProbabilityResultProxy& lhs, const ProbabilityResultProxy& rhs) {
return ProbabilityResultProxy(lhs.value() + rhs.value());
}
ProbabilityResultProxy operator-(const Probability& lhs, const Probability& rhs) {
return ProbabilityResultProxy(lhs.value() - rhs.value());
}
ProbabilityResultProxy operator-(const ProbabilityResultProxy& lhs, const Probability& rhs) {
return ProbabilityResultProxy(lhs.value() - rhs.value());
}
ProbabilityResultProxy operator-(const Probability& lhs, const ProbabilityResultProxy& rhs) {
return ProbabilityResultProxy(lhs.value() - rhs.value());
}
ProbabilityResultProxy operator-(const ProbabilityResultProxy& lhs, const ProbabilityResultProxy& rhs) {
return ProbabilityResultProxy(lhs.value() - rhs.value());
}
int main() {
Probability p1(0.75);
Probability p2(0.5);
Probability p3(0.6);
Probability result = p1 + p2 - p3;
std::cout << result.value() << "n";
try {
Probability result2 = p1 + p2;
std::cout << result2.value();
} catch (const std::runtime_error& e) {
std::cout << e.what() << "n";
}
return 0;
}
这里,为Probability
和ProbabilityResultProxy
的每个组合定义数学运算符。每个操作都返回一个代理对象,最后的赋值会导致执行边界检查。
如果你愿意,你可以让ProbabilityResultProxy
成为Probability
的私有成员类,并让操作员成为Probability
的朋友。这样可以防止任何人直接实例化代理类。
"反常"选项很简单:throw std::invalid_argument
。投球有点慢并不重要;无论如何你都得不到答案。好处是不抛出很快,因为优化器可以假设非异常路径的可能性要大得多。
就性能而言,拥有一个IntermediateResult
类可能是有益的,这样只会对返回到Probability
的最终分配进行范围检查。这避开了0.75+0.5-0.6
的例子。
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- C ++中无符号位长度类型之间的隐式转换,即uint8_t,uint16_t
- 为什么不同类型层次结构的指针之间的dynamic_cast定义得很好?
- 非类类型表达式的静态类型与动态类型之间的差异
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 指向 POD 类型的指针之间的静态转换与重新解释转换
- 在 Rcpp 中的字符串类型之间转换时出错
- 如何在不同类型的值之间进行选择以传递给多态函数?
- 如何声明不同类型的模板化类之间的转换
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- "+=" 操作在类型之间不起作用 std::复杂<double>和__complex__双精度
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 不同c++编译器之间的自动类型推导不匹配
- 类型测试对象的动态数组的这两个声明之间的区别?
- 使用模板在size_t和int之间进行隐式类型转换
- 为什么C++中的表达式类型在不同版本之间会发生变化
- 您可以在具有相同表示形式的类型之间reinterpret_cast吗?
- C和c++之间类型转换的差异