首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迭代时浮点数不精确

迭代时浮点数不精确
EN

Stack Overflow用户
提问于 2012-11-22 12:42:20
回答 3查看 261关注 0票数 3

我有一个函数,它根据range [0, 1]中的值计算3d中的一个点。我面临的问题是,二进制浮点数不能精确表示1。

在函数中求值的数学表达式能够计算t=1.0的值,但是该值永远不会被函数接受,因为它在计算之前检查范围。

代码语言:javascript
复制
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。问题可能是因为我在做这样的迭代:

代码语言:javascript
复制
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);
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-22 12:56:13

代码语言:javascript
复制
for (t=0; t <= 1.0; t += 0.1) {

您的问题是二进制浮点数不能准确地表示0.1

最接近的32位单精度0.1000000000000000055511151231257827021181583404541015625.浮点数为0.10000000149011119384765625,最接近64位双精度IEEE754浮点数。如果算法严格以32位精度执行,则将0.1f添加10次至0的结果是

代码语言:javascript
复制
1.00000011920928955078125

如果中间计算以比float更高的精度执行,它可能导致精确的1.0,甚至更小的数字。

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

代码语言:javascript
复制
for(k = 0; k <= 10; ++k) {
    t = k*0.1;

因为10 * 0.1f正是1.0

另一种选择是在curves_bezier函数中使用小公差,

代码语言:javascript
复制
if (t > 1 && t < 1 + epsilon) {
    t = 1;
}

对于一个合适的小epsilon,也许是float epsilon = 1e-6;

票数 8
EN

Stack Overflow用户

发布于 2012-11-22 12:55:09

二进制浮点数不能精确表示1。

证明它可以在这里找到

最精确表示= 1.0E0

可能会有问题

  1. 以基数为2的无限小数的分数阶数
  2. 太小而不能精确表示的数字
  3. 太大而不能表示而又不失去精度的数字。

1.0不是他们中的一员!

然而,0.1 是一个问题案例,违反了第1点,看看

最精确表示法= 1.00000001490116119384765625E-1

所以,如果你加起来0.1倍,你就会得到1.00000001490116119384765625E-0,它比1.0大。

(例子是IEEE754单精度32位浮点数)

可能的解决办法:

代码语言:javascript
复制
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语句中使用了额外的大括号。这样做,总有一天你会感谢自己的。)

票数 4
EN

Stack Overflow用户

发布于 2012-11-22 13:00:01

在比较浮点数时,您应该检查它们是否足够接近,不完全相等,因为其他答案中提到的原因如下:

代码语言:javascript
复制
#define EPSILON 0.000001f
#define FEQUAL(a,b) (fabs((a) - (b)) < EPSILON)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13512986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档