首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >0到1之间的数字类型

0到1之间的数字类型
EN

Stack Overflow用户
提问于 2015-11-20 17:39:04
回答 2查看 126关注 0票数 0

有没有一种自然的方法来定义一个介于0和1之间的数字类型?基本上,我们可以用double来做任何事情,问题是我应该在一些函数中定义一些边界检查,并且我有一个(可能很愚蠢的)想法,将边界检查外包给一个类,比如

代码语言:javascript
运行
复制
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;
    }
    // ...
    //
}

这种方法的问题可能是它会减慢每个操作的速度。有没有更快的边界检查方法?我还想知道如何处理上面代码中的“离谱”部分。

EN

回答 2

Stack Overflow用户

发布于 2015-11-20 18:12:58

您可以使用类Probability来强制执行边界,在内部存储一个双精度值。如果你想要像P(0.75) + P(0.5) - P(0.6)这样的操作,你可以让操作符返回一个代理对象,它不做边界检查。这个代理对象将有一个到Probability的转换操作符,并且Probability构造函数将检查边界。如果您只直接使用Probability类型,并允许ProbabilityResultProxy形式的临时函数,那么您将获得所需的行为。

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

Live example

代码语言:javascript
运行
复制
#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;
}

这里,为ProbabilityProbabilityResultProxy的每种组合定义了数学运算符。每个操作都返回一个代理对象,最终的赋值会导致执行边界检查。

如果您愿意,可以使ProbabilityResultProxy成为Probability的私有成员类,并使运算符成为Probability的朋友。这可以防止任何人直接实例化代理类。

票数 2
EN

Stack Overflow用户

发布于 2015-11-20 18:12:39

“变态”选项很简单:throw std::invalid_argument。抛出有一点慢并不重要;你无论如何都得不到答案。优点是不抛出很快,因为优化器可以假设非异常路径的可能性要大得多。

在性能方面,最好是有一个IntermediateResult类,这样只对返回给Probability的最终赋值进行范围检查。这就绕过了0.75+0.5-0.6示例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33823356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档