我有计算在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);
}
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;
。
二进制浮点数不能代表正好1
证明它可以可以在这里找到 。
最准确的代表性= 1.0E0
有可能是有问题的
- 这将有无限的小数位数为2基数小数
- 太小的数字准确地表示不失精度
- 数字太大不失精度来表示。
但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);
}
}
这样,二进制格式的错误没有得到总结!
( 注:我用额外的花括号的if
和else
报表做到这一点,你会感谢自己的一天。)
当比较浮点数,你应该检查它们是否足够接近并不完全相等,在其他的答案中提到的原因,是这样的:
#define EPSILON 0.000001f
#define FEQUAL(a,b) (fabs((a) - (b)) < EPSILON)