假设符合IEEE-754标准,是否保证在通过双重传输时保留浮动?
换句话说,以下断言是否会始终满足?
int main()
{
float f = some_random_float();
assert(f == (float)(double)f);
}
Run Code Online (Sandbox Code Playgroud)
假设f可以获取IEEE定义的任何特殊值,例如NaN和Infinity.
根据IEEE的说法,是否存在断言将被满足的情况,但是在通过double传输之后不能保留确切的位级表示?
代码段在C和C++中都有效.
我正在研究不同的内存块操作函数,在基准测试中我注意到,我的实现IsEqualRange(double* begin1, double* end1, double* begin2, double* end2)速度比std::equals(...)MSVC和GCC 快得多.进一步的调查表明,双打和浮标不是比较的memcmp,而是一个接一个的for循环.
在哪种情况下,浮点数的二进制比较会导致错误的结果?什么时候可以二进制比较(相等)浮点数/双打数组?我不应该使用其他基本类型memcmp吗?
每次我开始一个新项目,当我需要比较一些浮点数或双变量时,我会像这样编写代码:
if (fabs(prev.min[i] - cur->min[i]) < 0.000001 &&
fabs(prev.max[i] - cur->max[i]) < 0.000001) {
continue;
}
Run Code Online (Sandbox Code Playgroud)
然后我想摆脱这些神奇的变量0.000001(和双倍的0.00000000001)和fabs,所以我写了一个内联函数,有些定义:
#define FLOAT_TOL 0.000001
Run Code Online (Sandbox Code Playgroud)
所以我想知道是否有任何标准方法可以做到这一点?可能是一些标准的头文件?浮点数和双限制(最小值和最大值)也很好
这个主题在StackOverflow上出现了很多次,但我相信这是一个新的看法.是的,我已经阅读了布鲁斯道森的文章和每个计算机科学家应该知道的关于浮点算术的内容和这个很好的答案.
据我了解,在一个典型的系统上,比较浮点数是否相等有四个基本问题:
a-b是"小"取决于规模a和ba-b为"小"取决于类型a和b(例如浮动,双,长双)这个答案 - 又名."Google方法" - 似乎很受欢迎.它确实处理了所有棘手的案件.并且它确实非常精确地缩放比较,检查两个值是否在彼此的固定数量的ULP内.因此,例如,非常大的数字将"几乎相等"与无穷大相比较.
然而:
我想要类似的东西,但使用标准的C++并处理长双打.如果可能的话,我指的是C++ 03,如果需要,我指的是C++ 11.
这是我的尝试.
#include <cmath>
#include <limits>
#include <algorithm>
namespace {
// Local version of frexp() that handles infinities specially.
template<typename T>
T my_frexp(const T num, int *exp)
{
typedef std::numeric_limits<T> limits;
// Treat +-infinity as +-(2^max_exponent).
if (std::abs(num) > limits::max())
{
*exp …Run Code Online (Sandbox Code Playgroud) C#中的以下代码不起作用:
int iValue = 0;
double dValue = 0.0;
bool isEqual = iValue.Equals(dValue);
Run Code Online (Sandbox Code Playgroud)
那么,问题是:比较Double和Int的最佳方法是什么?
当在iPhone应用程序中使用double或float数据类型时,我遇到了"> ="和"<="比较的问题,因为当为变量分配一个带有一个小数位的数字时,例如4.2,浮点数或双精度数用于比较实际上可能有一个值,如4.1999998092651367.由于这种差异,诸如"> = 4.2"之类的比较是错误的而不是真实的.我该如何避免这个问题?
#include <cassert>
#include <cmath>
int main()
{
struct point_of_cone
{
double x, y;
double z = [&] { using std::sqrt; return sqrt(x * x + y * y); }();
};
point_of_cone p = {3.0, 4.0};
assert(p.z == 5.0);
}
Run Code Online (Sandbox Code Playgroud)
适用于clang++来自中继的工作正常,但是g++从中继失败并出现错误消息(链接):
错误:没有为此lambda函数捕获'this'
point_of_conein namespace范围的定义适用于两者.
使用[this]lambda捕获进行略微修改的定义也适用于全局或局部范围.
哪个编译器是对的?
可能重复:
与float文字的float比较中的奇怪输出
float f = 1.1;
double d = 1.1;
if(f == d) // returns 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对我来说似乎有点棘手,我不明白发生了什么.请尝试提供简单的测试.
看看这段代码:
#include <cmath>
#include <iostream>
using namespace std;
class Sphere
{
double r;
public:
double V() const { return (4/3) * 3.14 * pow(r,3); }
bool equal(const Sphere& s) const
{
cout << V() << " == " << s.V() << " : " << ( V() == s.V() );
return ( V() == s.V() );
}
explicit Sphere(double rr = 1): r(rr){}
};
main()
{
Sphere s(3);
s.equal(s);
}
Run Code Online (Sandbox Code Playgroud)
输出是84.78 == 84.78 : 0指同一方法每次都不返回相同的值,即使所有参数都是静态的?
但是如果我写的3.0不是 …
c++ ×7
double ×4
c ×2
comparison ×2
ieee-754 ×2
c# ×1
c++14 ×1
equals ×1
int ×1
iphone ×1
lambda ×1
math ×1
objective-c ×1
std ×1
visual-c++ ×1