比较两个double
或两个float
值的最有效方法是什么?
简单地这样做是不正确的:
bool CompareDoubles1 (double A, double B)
{
return A == B;
}
Run Code Online (Sandbox Code Playgroud)
但是像这样:
bool CompareDoubles2 (double A, double B)
{
diff = A - B;
return (diff < EPSILON) && (-diff < EPSILON);
}
Run Code Online (Sandbox Code Playgroud)
似乎浪费处理.
有谁知道更聪明的浮动比较器?
我知道你不能正常依赖双重或十进制类型值之间的相等,但我想知道0是否是特殊情况.
虽然我可以理解0.00000000000001和0.00000000000002之间的不精确,但0本身似乎很难搞砸,因为它什么都没有.如果你对什么都不精确,那就不再是什么了.
但我对这个话题知之甚少,所以我不能说.
double x = 0.0;
return (x == 0.0) ? true : false;
Run Code Online (Sandbox Code Playgroud)
这会永远回归真实吗?
到目前为止,我已经看到很多关于浮点数相等的帖子.对于"我们应该如何决定x和y是否相等?"这样的问题的标准答案.是
abs(x - y) < epsilon
Run Code Online (Sandbox Code Playgroud)
其中epsilon是一个固定的小常数.这是因为"操作数"x和y通常是涉及舍入误差的某些计算的结果,因此标准相等运算符==不是我们的意思,我们应该问的是x和y是否接近,不相等.
现在,我觉得如果x与y"几乎相等",那么x*10 ^ 20也应该与y*10 ^ 20"几乎相等",因为相对误差应该是相同的(但是"相对的" "到底是什么?" 但是对于这些大数字,上述测试将失败,即该解决方案不会"扩展".
你会如何处理这个问题?我们应该重新调整数字还是重新调整epsilon?怎么样?(或者我的直觉是错的吗?)
这是一个相关的问题,但我不喜欢它接受的答案,因为reinterpret_cast对我来说似乎有点棘手,我不明白发生了什么.请尝试提供简单的测试.
给定两个浮点数,我正在寻找一种有效的方法来检查它们是否具有相同的符号,假设如果这两个值中的任何一个为零(+0.0或-0.0),则应认为它们具有相同的符号标志.
例如,
SameSign
C++中一个天真但正确的实现是:
bool SameSign(float a, float b)
{
if (fabs(a) == 0.0f || fabs(b) == 0.0f)
return true;
return (a >= 0.0f) == (b >= 0.0f);
}
Run Code Online (Sandbox Code Playgroud)
假设IEEE浮点模型,这里的变体SameSign
编译为无分支代码(至少使用Visual C++ 2008):
bool SameSign(float a, float b)
{
int ia = binary_cast<int>(a);
int ib = binary_cast<int>(b);
int az = (ia & 0x7FFFFFFF) == 0;
int bz = (ib & 0x7FFFFFFF) == 0;
int ab = …
Run Code Online (Sandbox Code Playgroud) 考虑这个例子:
#include <vector>
#include <stdexcept>
struct A
{
float a;
float b;
float c;
float d;
};
struct B
{
A a;
std::vector<int> b;
};
int main() {
B b{};
if (b.a.a || b.a.b || b.a.c || b.a.d) throw std::runtime_error("Compiler bug?");
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,根据https://en.cppreference.com/w/cpp/language/zero_initialization,它不能抛出,因为应该为 B::a 执行零初始化,因为它应该为“值初始化类的成员没有构造函数的类型”。
如果抛出,是编译器错误还是我遗漏了什么?
[编辑]
这里启用了 clang 10 和优化,它只执行“mov eax, 2”和“ret”(意味着条件为假):https : //godbolt.org/z/CXrc3G
但是如果我移除大括号,它会执行“mov eax, 1”和“ret”(意味着条件为真)。但在这里我认为它可以返回任何它想要的东西,因为它只是 UB。 https://godbolt.org/z/tBvLzZ
所以似乎clang认为必须使用大括号进行零初始化。
编辑:我在英特尔的网站上提交了一个错误:https : //community.intel.com/t5/Intel-C-Compiler/Aggregate-initialization-bug-with-nested-struct/td-p/1178228
一位情报人员回复“我已将此问题报告给我们的开发人员。” 可怜的开发者,一手支持所有的icc开发。
我正在编写一个程序来检查给定的数字是否有一个整数的立方根.这是我的代码: -
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int main(int argc, char const *argv[])
{
double m;
int c=0;
int i;
for(i=2;i<=1000000;i++)
{
m = pow(i,(1./3.));
if(m-(int)m == 0)
{
c++;
}
}
cout<<c<<endl;
}
Run Code Online (Sandbox Code Playgroud)
这里c
存储具有整数立方根的数字的数量.我的代码的问题是它总是给出两个作为答案,而答案应该大于两个,因为有许多数字,如8,64,27 ....
我想知道为什么我得到两个结果,我无法捕捉到这个错误!!