【问题标题】:Why my compare operator is not comparing my point length and double value?为什么我的比较运算符不比较我的点长和双精度值?
【发布时间】:2020-09-14 07:55:06
【问题描述】:

我创建了新的运算符来比较我的点向量长度和双精度值。我有条件容忍小于 0.01 的差异。 当我使用此运算符比较我的 Point 和我的 double 值(接近后的两个值相同)但运算符 == 未返回 true 时。

class Point {
private:
    double x, y, z;
public:
    Point() { x = y = z = 0.0; }
    Point(double v) { x = y = z = v; }
    Point(double x, double y, double z){
        this->x = x; this->y = y; this->z = z;
    }
    double getLength(){
        return sqrt(pow(x,2)+pow(y,2)+pow(z,2));
    }
    friend const bool operator== (double &d, Point &v);
};

double approach(double num){
    return floor(num*100)/100;
}

const bool operator== (const double &d, Point &v){
    return (approach(d) == approach(v.getLength()));
}

int main()
{
    Point p1(3,4,1);
    cout << p1.getLength() << endl; // 5.09902
    cout << approach(p1.getLength()) << endl;
    cout << approach(5.091) << endl;
    if(5.091 == p1)
        cout << "True";
    return 0;
}

【问题讨论】:

  • 当我在 gcc 中测试它时,它输出"True"wandbox.org/permlink/KzPHzxaj6AOGhYh3
  • 它也输出True with clang
  • 我还得到了 clang-cl 的“True”输出,以及以下内容:警告:将浮点数与 == 或 != 进行比较是不安全的 [-Wfloat-equal] .
  • 哦,那应该是编译器错误。在 CodeBloacks 我看不到“真实”,但在 VS 中一切正常,谢谢你们 :)
  • 在 32 位 x86 系统上使用 gcc 可能无法打印 True,因为 bug 323 在某些情况下精度过高

标签: c++ operators logical-operators


【解决方案1】:

这个问题可以在 32 位 Intel 架构的 gcc 上重现,无需优化。 这是它发生的一个例子: compiler explorer example.

这是由于 gcc 的臭名昭著的323 bug,它难以与英特尔的 80 位浮点寄存器一起工作,这些寄存器比double 类型的 64 位更宽。一些值最终在 80 位寄存器中,一些值在 64 位内存值中。

在您的情况下,首先调用approach(d),然后在调用v.getLength() 时将其溢出到内存中。另一方面,approach(v.getLength()) 的值并没有溢出,而是获得了寄存器的所有 80 位精度。

当您比较一个 80 位的准确值和一个截断的 64 位值时,比较结果是false

一个可能的解决方案是避免在approach() 中除以 100,因为它是引入额外位的原因。相反,您可以尝试:

static constexpr double magnitude = 100.0;
const bool operator== (double d, const Point &v){
    return floor(d * magnitude) == floor(v.getLength() * magnitude));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 2018-03-11
    • 1970-01-01
    相关资源
    最近更新 更多