Chinaunix首页 | 论坛 | 博客
  • 博客访问: 334659
  • 博文数量: 57
  • 博客积分: 146
  • 博客等级: 入伍新兵
  • 技术积分: 769
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-29 14:57
文章分类
文章存档

2014年(39)

2013年(13)

2012年(5)

我的朋友

分类: C/C++

2014-07-04 15:42:05

1.小心浮点表达式重排

点击(此处)折叠或打开

  1. double x, y, z;
  2. /* ... */
  3. x = (x * y) * z; /* not equivalent to x *= y * z; */
  4. z = (x - y) + y ; /* not equivalent to z = x; */
  5. z = x + x * y; /* not equivalent to z = x * (1.0 + y); */
  6. y = x / 5.0; /* not equivalent to y = x * 0.2; */

2.理解浮点异常警告
C标准提供设施对浮点变量异常情况的检测。这些异常包括除数为零和上溢/下溢。然而, 有一些警告需要注意,要正确使用它们。


转换(Conversions):将浮点数转换整数可能导致一个“无效”浮点异常,如果发生这种情况该整数的值未定义的和不应使用。
另外,它不能被假定当一个非整数浮点值转换成一个整数,会引发“不精确”的浮点异常。

3.浮点数比较

代码:

点击(此处)折叠或打开

  1. float x;
  2. float y;
  3. /* Intermediate calculations on x, y */
  4. if ( fabsf(x-y) <= ( (fabsf(x) < fabsf(y) ? fabsf(y) : fabsf(x)) * FLT_EPSILON) ) {
  5. /* values are equal. */
  6. }
  7. else {
  8. /* values are non equal. */
  9. }
FLT_EPSILON用于float类型。
它是满足 x+1.0不等于1.0的最小的正数。
也就是说,所有比FLT_EPSILON小的正数x,x+1.0==1.0都是成立的。

4.调用数学函数前进行边界检测




a.acos(x),asin(x):
错误代码

点击(此处)折叠或打开

  1. float x, result;
  2. result = acos(x)
正确代码:

点击(此处)折叠或打开

  1. float x, result;
  2. if ( islessequal(x,-1) || isgreaterequal(x, 1) ){
  3. /* handle domain error */
  4. }
  5. result = acos(x)

b.atan2(x,y)
错误代码:x,y不能为0

点击(此处)折叠或打开

  1. float x, y, result;
  2. result = atan2(y, x)
正确代码:

点击(此处)折叠或打开

  1. float x, y, result;
  2. if ( fpclassify(x) == FP_ZERO && fpclassify(y) == FP_ZERO){
  3. /* handle domain error */
  4. }
  5. result = atan2(y, x)

c.log(x),log10(X)
错误代码:x不能小于等于0

点击(此处)折叠或打开

  1. float result, x;
  2. result = log(x)

正确代码:

点击(此处)折叠或打开

  1. float result, x;
  2. if (islessequal(x, 0)){
  3. /* handle domain and range errors */
  4. }
  5. result = log(x)

d.pow(x,y)
错误代码:x不能为0同时Y小于等于0.

点击(此处)折叠或打开

  1. float x, y, result;
  2. result = pow(x, y)

正确代码:

点击(此处)折叠或打开

  1. float x, y, result;
  2. if (fpclassify(x) == FP_ZERO && islessequal(y, 0)){
  3. /* handle domain error condition */
  4. }
  5. result = pow(x, y)

e.sqrt(x)
错误代码:x不能为负数

点击(此处)折叠或打开

  1. float x, result;
  2. result = sqrt(x)

正确代码:

点击(此处)折叠或打开

  1. float x, result;
  2. if (isless(x, 0)){
  3. /* handle domain error */
  4. }
  5. result = sqrt(x)


5.整数转换成浮点数进行浮点运算
错误代码:

点击(此处)折叠或打开

  1. short a = 533;
  2. int b = 6789;
  3. long c = 466438237;
  4. float d = a / 7; /* d is 76.0 */
  5. double e = b / 30; /* e is 226.0 */
  6. double f = c * 789; /* 由于溢出,F可能为负数 */
a/7,b/30,c*789都是进行整型运算然后转换成double。

正确代码:

点击(此处)折叠或打开

  1. short a = 533;
  2. int b = 6789;
  3. long c = 466438237;
  4. float d = a / 7.0f; /* d is 76.14286 */
  5. double e = b / 30.; /* e is 226.3 */
  6. double f = (double)c * 789; /* f is 360*/
引入7.0f,30.,(doulbe)c来进行浮点运算操作。

正确代码2:

点击(此处)折叠或打开

  1. short a = 533;
  2. int b = 6789;
  3. long c = 466438237;
  4. float d = a;
  5. double e = b;
  6. double f = c;
  7. d /= 7; /* d is 76.14286 */
  8. e /= 30; /* e is 226.3 */
  9. f /= 789; /* f is 591176.47275 */

6.确保降级成浮点的值属于浮点范围内

C99规定:当double降职为float或long double降级为double或float,如果转换的值在表示的值的范围之外行为是未定义的
错误代码:

点击(此处)折叠或打开

  1. long double ld;
  2. double d1;
  3. double d2;
  4. float f1;
  5. float f2;
  6. /* initialization
  7. f1 = (float)d1;
  8. f2 = (float)ld;
  9. d2 = (double)ld
d1的值已经超出了float可表示的范围,ld的值已经超出了float或double可表示的范围。

正确代码:进行范围判断

点击(此处)折叠或打开

  1. #include <float.h>
  2. long double ld;
  3. double d1;
  4. double d2;
  5. float f1;
  6. float f2;
  7. /* initializations */
  8. if (d1 > FLT_MAX || d1 < -FLT_MAX) {
  9. /* Handle error condition */
  10. } else {
  11. f1 = (float)d1;
  12. }
  13. if (ld > FLT_MAX || ld < -FLT_MAX) {
  14. /* Handle error condition */
  15. } else {
  16. f2 = (float)ld;
  17. }
  18. if (ld > DBL_MAX || ld < -DBL_MAX) {
  19. /* Handle error condition */
  20. } else {
  21. d2 = (double)ld;
  22. }




阅读(749) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~