Squ*_*idy 59 c++ floating-point c++11
我想将float的最小可能值添加到float中.所以,例如,我尝试这样做以获得1.0 +最小的浮点数:
float result = 1.0f + std::numeric_limits<float>::min();
Run Code Online (Sandbox Code Playgroud)
但在这之后,我得到以下结果:
(result > 1.0f) == false
(result == 1.0f) == true
Run Code Online (Sandbox Code Playgroud)
我正在使用Visual Studio 2015.为什么会这样?我该怎么做才能绕过它?
Ben*_*ley 86
如果你希望在1之后有下一个可表示的值,那么std::nextafter从<cmath>标题中有一个被调用的函数.
float result = std::nextafter(1.0f, 2.0f);
Run Code Online (Sandbox Code Playgroud)
它从第二个参数方向的第一个参数开始返回下一个可表示的值.因此,如果您想要找到低于1的下一个值,您可以这样做:
float result = std::nextafter(1.0f, 0.0f);
Run Code Online (Sandbox Code Playgroud)
将最小的正可表示值添加到1不起作用,因为1和下一个可表示值之间的差值大于0和下一个可表示值之间的差值.
650*_*502 41
你观察到的"问题"是因为浮点运算的本质.
在FP中,精度取决于比例; 围绕价值1.0的精度是不够的,能够区分1.0并1.0+min_representable在那里min_representable可能是最小的值大于零(即使我们只考虑最小规格化数,std::numeric_limits<float>::min()...最小的非正规的幅度要小的另一个几个数量级).
例如,对于双精度64位IEEE754浮点数,在x=10000000000000000(10 16)的范围内,不可能区分x和x+1.
分辨率随着比例变化的事实是名称"浮点"的原因,因为小数点"浮动".相反,固定点表示将具有固定的分辨率(例如,在单位以下具有16位二进制数字,精度为1/65536~0.00001).
例如,在IEEE754 32位浮点格式中,符号有一位,指数有8位,尾数有31位:
最小值,eps例如,1.0f + eps != 1.0f可用作预定义常量FLT_EPSILON,或std::numeric_limits<float>::epsilon.另请参阅维基百科上的机器epsilon,其中讨论了epsilon如何与舍入错误相关.
即epsilon是您在此处所期望的最小值,在添加到1.0时会产生差异.
更常见的版本(对于1.0以外的数字)在最后一个位置(尾数)称为1个单位.请参阅维基百科的ULP文章.
Mat*_*lia 20
min是(规范化形式)浮点数可以假设的最小非零值,即大约2 -126(-126是浮点数的最小允许指数); 现在,如果你把它加到1,你仍然会得到1,因为a float只有23位的尾数,所以这么小的变化不能用这么大的数字来表示(你需要一个126位的尾数才能看到一个改变总和2 -126到1).
相反,最小可能的变化是epsilon(所谓的机器epsilon),实际上是2 -23 - 因为它影响尾数的最后一位.
| 归档时间: |
|
| 查看次数: |
4983 次 |
| 最近记录: |