1.小心浮点表达式重排
-
double x, y, z;
-
/* ... */
-
x = (x * y) * z; /* not equivalent to x *= y * z; */
-
z = (x - y) + y ; /* not equivalent to z = x; */
-
z = x + x * y; /* not equivalent to z = x * (1.0 + y); */
-
y = x / 5.0; /* not equivalent to y = x * 0.2; */
2.理解浮点异常警告
C标准提供设施对浮点变量异常情况的检测。这些异常包括除数为零和上溢/下溢。然而, 有一些警告需要注意,要正确使用它们。
转换(Conversions):将浮点数转换整数可能导致一个“无效”浮点异常,如果发生这种情况该整数的值未定义的和不应使用。
另外,它不能被假定当一个非整数浮点值转换成一个整数,会引发“不精确”的浮点异常。
3.浮点数比较
代码:
-
float x;
-
float y;
-
/* Intermediate calculations on x, y */
-
if ( fabsf(x-y) <= ( (fabsf(x) < fabsf(y) ? fabsf(y) : fabsf(x)) * FLT_EPSILON) ) {
-
/* values are equal. */
-
}
-
else {
-
/* values are non equal. */
-
}
FLT_EPSILON用于float类型。
它是满足 x+1.0不等于1.0的最小的正数。也就是说,所有比FLT_EPSILON小的正数x,x+1.0==1.0都是成立的。
4.调用数学函数前进行边界检测

a.acos(x),asin(x):
错误代码
-
float x, result;
-
result = acos(x)
正确代码:
-
float x, result;
-
if ( islessequal(x,-1) || isgreaterequal(x, 1) ){
-
/* handle domain error */
-
}
-
result = acos(x)
b.atan2(x,y)
错误代码:x,y不能为0
-
float x, y, result;
-
result = atan2(y, x)
正确代码:
-
float x, y, result;
-
if ( fpclassify(x) == FP_ZERO && fpclassify(y) == FP_ZERO){
-
/* handle domain error */
-
}
-
result = atan2(y, x)
c.log(x),log10(X)
错误代码:x不能小于等于0
-
float result, x;
-
result = log(x)
正确代码:
-
float result, x;
-
if (islessequal(x, 0)){
-
/* handle domain and range errors */
-
}
-
result = log(x)
d.pow(x,y)
错误代码:x不能为0同时Y小于等于0.
-
float x, y, result;
-
result = pow(x, y)
正确代码:
-
float x, y, result;
-
if (fpclassify(x) == FP_ZERO && islessequal(y, 0)){
-
/* handle domain error condition */
-
}
-
result = pow(x, y)
e.sqrt(x)
错误代码:x不能为负数
-
float x, result;
-
result = sqrt(x)
正确代码:
-
float x, result;
-
if (isless(x, 0)){
-
/* handle domain error */
-
}
-
result = sqrt(x)
5.
整数转换成浮点数进行浮点运算
错误代码:
-
short a = 533;
-
int b = 6789;
-
long c = 466438237;
-
float d = a / 7; /* d is 76.0 */
-
double e = b / 30; /* e is 226.0 */
-
double f = c * 789; /* 由于溢出,F可能为负数 */
a/7,b/30,c*789都是进行整型运算然后转换成double。
正确代码:
-
short a = 533;
-
int b = 6789;
-
long c = 466438237;
-
float d = a / 7.0f; /* d is 76.14286 */
-
double e = b / 30.; /* e is 226.3 */
-
double f = (double)c * 789; /* f is 360*/
引入7.0f,30.,(doulbe)c来进行浮点运算操作。
正确代码2:
-
short a = 533;
-
int b = 6789;
-
long c = 466438237;
-
float d = a;
-
double e = b;
-
double f = c;
-
d /= 7; /* d is 76.14286 */
-
e /= 30; /* e is 226.3 */
-
f /= 789; /* f is 591176.47275 */
6.确保降级成浮点的值属于浮点范围内
C99规定:当double被降职为float或long double降级为double或float,如果被转换的值在表示的值的范围之外,该行为是未定义的。
错误代码:
-
long double ld;
-
double d1;
-
double d2;
-
float f1;
-
float f2;
-
/* initialization
-
f1 = (float)d1;
-
f2 = (float)ld;
-
d2 = (double)ld
d1的值已经超出了float可表示的范围,ld的值已经超出了float或double可表示的范围。
正确代码:进行范围判断
-
#include <float.h>
-
long double ld;
-
double d1;
-
double d2;
-
float f1;
-
float f2;
-
/* initializations */
-
if (d1 > FLT_MAX || d1 < -FLT_MAX) {
-
/* Handle error condition */
-
} else {
-
f1 = (float)d1;
-
}
-
if (ld > FLT_MAX || ld < -FLT_MAX) {
-
/* Handle error condition */
-
} else {
-
f2 = (float)ld;
-
}
-
if (ld > DBL_MAX || ld < -DBL_MAX) {
-
/* Handle error condition */
-
} else {
-
d2 = (double)ld;
-
}
阅读(749) | 评论(0) | 转发(0) |