关于C语言中的DBL_EPSILON和Machine-Epsilon的困惑 [英] Confusion about DBL_EPSILON and Machine-Epsilon in C
问题描述
对于Machine-Epsilon似乎有两个定义:
There seem to be two definitions for the Machine-Epsilon:
- 将实数舍入到下一个浮点数时的最大相对误差.
- 最小正数,例如1.0 + machine_eps!= 1.0
首先,我看不到两者之间的关系. 根据我的理解,第二个DBL_EPSILON不符合定义2:
First of all, i fail to see how these two correlate. Second DBL_EPSILON does not conform to Definition 2 in my understanding:
以下程序打印:
DBL_EPSILON: 2.220446049250313080847e-16
DBL_EPSILON / 2: 1.110223024625156540424e-16
1.0 + DBL_EPSILON: 1.000000000000000222045e+00
1.0 + DBL_EPSILON / 2: 1.000000000000000000000e+00
m_eps 2.220446049250313080847e-16
m_eps -1u 2.220446049250312834328e-16
1.0 + m_eps -1u 1.000000000000000222045e+00
(m_eps -1u < DBL_EPSILON): True
(m_eps -1u == DBL_EPSILON/2): False
m_eps -1u
应该小一些,但实际上应接近DBL_EPSILON
.和
定义2)1.0 + m_eps -1u
不应评估为1.0
吗?为什么有必要
为此将DBL_EPSILON
分配2?
m_eps -1u
should be a number smaller but really close to DBL_EPSILON
. With
Definiton 2) should 1.0 + m_eps -1u
not evaluate to 1.0
? Why is it necessary
to devide DBL_EPSILON
by 2 for this?
#include <stdout.h>
#include <stdint.h>
#inlcude <float.h>
union Double_t {
double f;
int64_t i;
};
int main(int argc, char *argv[])
{
union Double_t m_eps;
printf("DBL_EPSILON: \t\t%.*e\n", DECIMAL_DIG, DBL_EPSILON);
printf("DBL_EPSILON / 2: \t%.*e\n", DECIMAL_DIG, DBL_EPSILON / 2);
printf("1.0 + DBL_EPSILON: \t%.*e\n", DECIMAL_DIG, 1.0 + DBL_EPSILON);
printf("1.0 + DBL_EPSILON / 2: \t%.*e\n", DECIMAL_DIG, 1.0 + DBL_EPSILON / 2);
m_eps.f = DBL_EPSILON;
printf("\nm_eps \t\t\t%.*e\n", DECIMAL_DIG, m_eps.f);
m_eps.i -= 1;
printf("m_eps -1u\t\t%.*e\n", DECIMAL_DIG, m_eps.f);
printf("\n1.0 + (m_eps -1u)\t\t%.*e\n", DECIMAL_DIG, 1.0 + m_eps.f);
printf("\n(m_eps -1u < DBL_EPSILON): %s\n",
(m_eps.f < DBL_EPSILON) ? "True": "False"
);
printf("(m_eps -1u == DBL_EPSILON/2): %s\n",
(DBL_EPSILON/2 == m_eps.f) ? "True": "False"
);
return 0;
}
推荐答案
错误地定义了DBL_EPSILON
,您引用它为最小正数,例如1.0 + machine_eps!= 1".您甚至可以在标准库中找到它,也可以在StackOverflow上的其他很好的答案中找到它.在标准库中找到该注释后,该注释位于一个值附近,该值显然与注释不对应,但与正确的定义对应:
A wrong definition of DBL_EPSILON
, the one you quote as "The minimum positive number such that 1.0 + machine_eps != 1", is floating around. You can even find it in standard libraries and in otherwise fine answers on StackOverflow. When found in standard libraries, it is in a comment near a value that obviously does not correspond to the comment, but corresponds to the correct definition:
DBL_EPSILON:这是1与最小之间的差
double
类型的浮点数大于1.(正确的定义来自GNU C库)
DBL_EPSILON: This is the difference between 1 and the smallest floating point number of type
double
that is greater than 1. (correct definition taken from the GNU C library)
C99标准是这样表达的:
The C99 standard phrases it this way:
在给定的浮点类型b ^(1-p)中可表示的1和大于1的最小值之间的差
the difference between 1 and the least value greater than 1 that is representable in the given floating point type, b^(1−p)
这可能是造成您困惑的原因.忘记错误的定义.我在此处(其中非常像您的问题).
This is probably the cause of your confusion. Forget about the wrong definition. I wrote a rant about this here (which is very much like your question).
您的问题中的另一个定义是将四舍五入到一个下一个浮点数时的最大相对误差",当四舍五入的结果是一个正常的浮点数时,它是正确的.将实数浮点到有限的浮点数会产生一个浮点数,该浮点数在实数值的1/2 ULP之内.对于正常的浮点数,此1/2 ULP绝对错误会转换为相对误差,该相对误差可能介于DBL_EPSILON/2和DBL_EPSILON/4之间,具体取决于浮点数在其
The other definition in your question, "the maximum relative Error when rounding a real number to the next floating-point number", is correct-ish when the result of the rounding is a normal floating-point number. Rounding a real to finite floating-point number produces a floating-point number within 1/2 ULP of the real value. For a normal floating-point number, this 1/2 ULP absolute error translates to a relative error that can be between DBL_EPSILON/2 and DBL_EPSILON/4 depending where the floating-point number is located in its binade.
这篇关于关于C语言中的DBL_EPSILON和Machine-Epsilon的困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!