浮点数不精确而迭代(floating point number imprecision while

2019-07-04 01:33发布

我有计算在3D的点的函数隔开基于值在范围[0, 1] 我面临的问题是,一个二进制浮点数字不能代表准确1。

即在函数评估的数学表达式是能够计算的值对于t=1.0 ,但该值永远不会由功能,因为它会检查是否为范围计算之前被接受。

curves_error curves_bezier(curves_PointList* list, curves_Point* dest, curves_float t) {
    /* ... */
    if (t < 0 || t > 1)
        return curves_invalid_args;
    /* ... */
    return curves_no_error;
}

我怎样才能利用此功能,在计算三维点t=1.0 ? 我听说过一些,一个ELLIPSIS前一段时间,我认为有一个这样的问题做的,但我不知道。

谢谢

编辑 :好的,我很抱歉。 我假设浮动不能只代表1,因为这个问题,我面对的问题。 该问题可能是因为我是做一个像这样的迭代:

for (t=0; t <= 1.0; t += 0.1) {
    curves_error error = curves_bezier(points, point, t);
    if (error != curves_no_error)
        printf("Error with t = %f.\n", t);
    else
        printf("t = %f is ok.\n", t);
}

Answer 1:

for (t=0; t <= 1.0; t += 0.1) {

你的问题是,一个二进制浮点数字不能完全代表0.1

最接近的32位单精度IEEE754浮点数为0.100000001490116119384765625与最接近的64位双精度一个0.1000000000000000055511151231257827021181583404541015625。 如果在32位精度严格执行的算术,加入的结果0.1f十倍至0是

1.00000011920928955078125

如果中间计算在大于精度进行float有,也可能会导致准确1.0或甚至稍微小的数字。

为了解决您的问题,在这种情况下,你可以使用

for(k = 0; k <= 10; ++k) {
    t = k*0.1;

因为10 * 0.1f正好是1.0

另一种选择是在你使用小公差curves_bezier功能,

if (t > 1 && t < 1 + epsilon) {
    t = 1;
}

为适当小的ε,也许float epsilon = 1e-6;



Answer 2:

二进制浮点数不能代表正好1

证明它可以可以在这里找到 。

最准确的代表性= 1.0E0

有可能是有问题的

  1. 这将有无限的小数位数为2基数小数
  2. 太小的数字准确地表示不失精度
  3. 数字太大不失精度来表示。

1.0是没有人!

但是 0.1是一个问题的情况下,违反点数1,看看这个 :

最精确的表示= 1.00000001490116119384765625E-1

所以,如果你把0.1的十倍,你会得到1.00000001490116119384765625E-0是大于1.0

(实例是在IEEE754单精度的32位浮点数)

可能的解决方法:

int i;
for (i=0; i <= 10; i++) {
    t=i/10.0;
    curves_error error = curves_bezier(points, point, t);
    if (error != curves_no_error) {
        printf("Error with t = %f.\n", t);
    }
    else {
        printf("t = %f is ok.\n", t);
    }
}

这样,二进制格式的错误没有得到总结!

注:我用额外的花括号的ifelse报表做到这一点,你会感谢自己的一天。)



Answer 3:

当比较浮点数,你应该检查它们是否足够接近并不完全相等,在其他的答案中提到的原因,是这样的:

#define EPSILON 0.000001f
#define FEQUAL(a,b) (fabs((a) - (b)) < EPSILON)


文章来源: floating point number imprecision while iterating