C++ 数字类型介于0和1之间

C++ 数字类型介于0和1之间,c++,C++,是否有一种自然的方法来定义介于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和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;
    }
    // ...
    //
}
类概率{
//概率值
双val;
概率(双val):值(val){
//如果val>1或val<0,则会出现异常
//...
//
};
//运营商,如
概率运算符+(概率常数a、概率常数b){
双结果a.val+b.val;
如果((结果>1)| |(结果<0)){
//发疯
结果=0
}
返回结果;
}
// ...
//
}
这种方法的问题可能是它会减慢每个操作。有没有更快的绑定检查方法?我还想知道如何处理上面代码中的“畸形”部分。

畸形”选项很简单:
throw std::invalid_argument
。投掷有点慢并不重要;反正你也得不到答案。好处是不抛出速度很快,因为优化器可以假设非异常路径的可能性更大

性能方面,最好使用
IntermediateResult
类,以便只检查返回到
概率的最终赋值。这避开了
0.75+0.5-0.6
示例。

这个“抓狂”选项很简单:
抛出std::invalid_参数。投掷有点慢并不重要;反正你也得不到答案。好处是不抛出速度很快,因为优化器可以假设非异常路径的可能性更大


性能方面,最好使用
IntermediateResult
类,以便只检查返回到
概率的最终赋值。这避开了
0.75+0.5-0.6
示例。

您可以使用类
概率
强制执行边界,在内部存储双精度。如果希望
P(0.75)+P(0.5)-P(0.6)
等操作正常工作,可以让操作符返回一个代理对象,该对象不进行边界检查。这个代理对象将有一个到
概率
的转换操作符,
概率
构造函数将检查边界。如果您只直接使用
Probability
类型,并允许形式为
ProbabilityResultProxy
的临时变量,您将获得所需的行为

下面的示例概述了这种方法。很明显,在实际实现中,您可能会缺少很多东西,但我希望将重点放在一个特定的解决方案上,而不是提供一个完整的类

:

#包括
类概率{
公众:
概率(双值){
如果(值<0 | |值>1)抛出std::runtime_错误(“无效概率”);
价值=价值;
}
双值()常量{返回值}
私人:
双值;
};
类概率ResultProxy{
公众:
显式ProbabilityResultProxy(双p):值_Up{}
双值()常量{返回值}
算子概率(){
返回概率(值u);
}
私人:
双值;
};
ProbabilityResultProxy运算符+(常数概率和lhs、常数概率和rhs){
返回ProbabilityResultProxy(lhs.value()+rhs.value());
}
ProbabilityResultProxy运算符+(常量ProbabilityResultProxy和lhs、常量Probability和rhs){
返回ProbabilityResultProxy(lhs.value()+rhs.value());
}
ProbabilityResultProxy运算符+(常数概率和lhs、常数概率ResultProxy和rhs){
返回ProbabilityResultProxy(lhs.value()+rhs.value());
}
ProbabilityResultProxy运算符+(常量ProbabilityResultProxy和lhs、常量ProbabilityResultProxy和rhs){
返回ProbabilityResultProxy(lhs.value()+rhs.value());
}
ProbabilityResultProxy运算符-(常数概率和lhs,常数概率和rhs){
返回ProbabilityResultProxy(lhs.value()-rhs.value());
}
ProbabilityResultProxy运算符-(常量ProbabilityResultProxy和lhs,常量Probability和rhs){
返回ProbabilityResultProxy(lhs.value()-rhs.value());
}
ProbabilityResultProxy运算符-(常量概率和lhs,常量概率ResultProxy和rhs){
返回ProbabilityResultProxy(lhs.value()-rhs.value());
}
ProbabilityResultProxy运算符-(常量ProbabilityResultProxy和lhs,常量ProbabilityResultProxy和rhs){
返回ProbabilityResultProxy(lhs.value()-rhs.value());
}
int main(){
概率p1(0.75);
概率p2(0.5);
概率p3(0.6);
概率结果=p1+p2-p3;

std::cout您可以使用类
Probability
来强制执行边界,在内部存储一个double。如果您需要诸如
p(0.75)+p(0.5)-p(0.6)之类的操作
要工作,可以让操作符返回一个代理对象,该对象不进行边界检查。此代理对象将有一个到
概率
的转换操作符,而
概率
构造函数将检查边界。如果您只直接使用
概率
类型,并允许f的临时值orm
ProbabilityResultProxy
,您将获得所需的行为

下面的示例概述了这种方法。很明显,在实际实现中,您可能会缺少很多东西,但我想专注于一个特定的解决方案,而不是提供一个完整的类

:

#包括
类概率{
公众:
概率(双值){
如果(值<0 | |值>1)抛出std::runtime_错误(“无效概率”);
价值=价值;
}
双值()常量{返回值}
私人:
双值;
};
类概率ResultProxy{
公众:
显式ProbabilityResultProxy(双p):值_Up{}
双值()常量{return v
#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;
}