免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3858 | 回复: 10
打印 上一主题 下一主题

请问x是float类型,什么情况下x!=x为真 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-07-10 10:21 |只看该作者 |倒序浏览
rt

论坛徽章:
0
2 [报告]
发表于 2005-07-10 20:36 |只看该作者

请问x是float类型,什么情况下x!=x为真

请看这一例(WIN2000+VC6.0):
  1. /***********************************************
  2. *file name    : float_accuracy.c
  3. *description : x是float类型,什么情况下x!=x为真
  4. *note           : 若在判断x!=x前对x进行了修改,则
  5.                   有可能使x!=x为真
  6. *author        : kernelxu
  7. *resource     : http://bbs.chinaunix.net/forum/
  8.                       viewtopic.php?t=575049&show_type=
  9. *date            : 2005/07/10
  10. ***********************************************/

  11. #include <stdio.h>;

  12. /**********************************************
  13. *function name :     main()
  14. ***********************************************/
  15. int main(void)
  16. {
  17.         float x = (float)1e-3;

  18.         x = x + 1;
  19.         if (x != x)
  20.         {
  21.                 printf("x is UNequal to x!!\n");
  22.         }
  23.         else
  24.         {
  25.                 printf("x is equal to x!\n");
  26.         }
  27.    
  28.         return 0;
  29. }/*END OF main()*/
复制代码

结果:
x is UNequal to x!!
在x!=x判断前对x进行了加法运算,x!=x为真

———————————————————————————————————

第二例
  1. /***********************************************
  2. *file name    : float_accuracy.c
  3. *description : x是float类型,什么情况下x!=x为真
  4. *note           : 若在判断x!=x前对x进行了修改,
  5.                   则有可能使x!=x为真
  6. *author       : kernelxu
  7. *resource    : http://bbs.chinaunix.net/forum/
  8.                      viewtopic.php?t=575049&show_type=
  9. *date          : 2005/07/10
  10. ***********************************************/

  11. #include <stdio.h>;

  12. /**********************************************
  13. *function name :    main()
  14. ***********************************************/
  15. int main(void)
  16. {
  17.         float x = (float)1e-3;

  18.                 x = (float)((int)x + 1);
  19.         if (x != x)
  20.         {
  21.                 printf("x is UNequal to x!!\n");
  22.                
  23.         }
  24.         else
  25.         {
  26.                 printf("x is equal to x!\n");
  27.         }
  28.    
  29.         return 0;
  30. }/*END OF main()*/
复制代码

结果:
x=0.001000
x is equal to x!
在x!=x判断前对x进行了又一种加法运算,x!=x为假

——————————————————————————————————
查看相应汇编代码:
第一例:
x = x + 1;
0040E9DF   fld         dword ptr [ebp-4]
0040E9E2   fadd        dword ptr [string "x = %f\n" (00425000)]
0040E9E8   fst         dword ptr [ebp-4]

第二例:
x = (float)((int)x + 1);
0040E9DF   fld         dword ptr [ebp-4]
0040E9E2   call        __ftol (0040ea2c)
0040E9E7   add         eax,1
0040E9EA   mov         dword ptr [ebp-8],eax
0040E9ED   fild        dword ptr [ebp-8]

0040E9F0   fst         dword ptr [ebp-4]

两种修改的区别就在于:
第一例是做的double型加法;第二例做的是整型加法。double型运算存在误差,且对double型数据进行关系运算本身就存在误差。

论坛徽章:
0
3 [报告]
发表于 2005-07-10 22:17 |只看该作者

请问x是float类型,什么情况下x!=x为真

楼主的意思不会是,不对x的值进行修改的情况下叫x!=x为真吧?

论坛徽章:
0
4 [报告]
发表于 2005-07-11 09:56 |只看该作者

请问x是float类型,什么情况下x!=x为真

狂晕!

论坛徽章:
0
5 [报告]
发表于 2005-07-11 11:03 |只看该作者

请问x是float类型,什么情况下x!=x为真

原帖由 "Ecore"]楼主的意思不会是,不对x的值进行修改的情况下叫x!=x为真吧?[/quote 发表:

但是,你要是在修改x的值和判断x!=x之间再加上一语句,x!=x又变假了。
Win2000+VC6.0下运行:
  1. /***********************************************
  2. *file name    : float_accuracy.c
  3. *description : x是float类型,什么情况下x!=x为真
  4. *note           : 若在判断x!=x前对x进行了修改,则
  5.                有可能使x!=x为真,在此间加语句又可能使其变假
  6. *author        : kernelxu
  7. *resource     : http://bbs.chinaunix.net/forum/
  8.                      viewtopic.php?t=575049&show_type=
  9. *date            : 2005/07/10
  10. ***********************************************/

  11. #include <stdio.h>;

  12. /**********************************************
  13. *function name :     main()
  14. ***********************************************/
  15. int main(void)
  16. {
  17.    float x = (float)1e-3;

  18.    x = x + 1;
  19.    printf("HELLO WORLD!\n");    /*加上这一句*/
  20.    if (x != x)
  21.    {
  22.       printf("x is UNequal to x!!\n");
  23.    }
  24.    else
  25.    {
  26.       printf("x is equal to x!\n");
  27.    }
  28.   
  29.    return 0;
  30. }/*END OF main()*/
复制代码

结果:
[quote]原来结果为:
x is UNequal to x!!
加了:
printf("HELLO WORLD!\n";   
后,结果变为:
x is equal to x!
难道在printf("HELLO WORLD!\n";
执行期间,x的值得到了调整?

查看其汇编:
x = x + 1;
0040E9DF   fld         dword ptr [ebp-4]
0040E9E2   fadd        dword ptr [__real@4@3fff8000000000000000 (00424030)]
0040E9E8   fstp        dword ptr [ebp-4]

22:       printf("HELLO WORLD!\n";
0040E9EB   push        offset string "x = %f\n" (0042500
0040E9F0   call        printf (00401090)
0040E9F5   add         esp,4

与不加printf("HELLO WORLD!\n";对比:
x = x + 1;
0040E9DF   fld         dword ptr [ebp-4]
0040E9E2   fadd        dword ptr [string "x = %f\n" (00425000)]
0040E9E8   fst         dword ptr [ebp-4]

处理上就有所差别,具体是什么样的一个过程呢?
。。。。。。

论坛徽章:
0
6 [报告]
发表于 2005-07-11 16:44 |只看该作者

请问x是float类型,什么情况下x!=x为真

谢谢大家
我想此题目的关键在于x是float类型
只要提供x!=x为真的情形就可以了。
感谢kernelxu

论坛徽章:
0
7 [报告]
发表于 2005-07-11 18:00 |只看该作者

请问x是float类型,什么情况下x!=x为真

在本人的机器上(win xp; Vc++6.0)输出都是:
x is equal to x!

第一例的汇编代码为:

12:      x = x + 1;
0040102F   fld         dword ptr [ebp-4]
00401032   fadd        dword ptr [__real@4@3fff8000000000000000 (00424030)]
00401038   fstp        dword ptr [ebp-4]


与你的不同,倒是与你第二次在x=x+1后面加了一个句子的汇编代码很象,why??

论坛徽章:
0
8 [报告]
发表于 2005-07-11 21:27 |只看该作者

请问x是float类型,什么情况下x!=x为真

原帖由 "zhaoshj" 发表:


与你的不同,倒是与你第二次在x=x+1后面加了一个句子的汇编代码很象,why??

我又试了一遍,输出结果确实是那样的!
第一贴上的第一例汇编确实是你说的那样,我所给的汇编是以下代码的:
  1. /***********************************************
  2. *file name   : float_accuracy.c
  3. *description : x是float类型,什么情况下x!=x为真
  4. *note        : 若在判断x!=x前对x进行了访问,
  5.                则有可能使x!=x为真
  6. *author      : kernelxu
  7. *resource    : http://bbs.chinaunix.net/forum/
  8.               viewtopic.php?t=575049&show_type=
  9. *date        : 2005/07/10
  10. ***********************************************/

  11. #include <stdio.h>;

  12. /**********************************************
  13. *function name :    main()
  14. ***********************************************/
  15. int main(void)
  16. {
  17.         float x = (float)1e-3;

  18.                x = x + 1;
  19.            //printf("x = %f\n", x);/*比第一例多的,但注释掉了*/
  20.            //printf("x != x is %d\n", (x != x)); /*比第一例多的,但注释掉了*/
  21.         if (x != x)
  22.         {
  23.                 printf("x is UNequal to x!!\n");
  24.                 //printf("x != x is %d\n", (x != x));
  25.         }
  26.         else
  27.         {
  28.                 printf("x is equal to x!\n");
  29.                                //printf("x != x is %d\n", (x != x));
  30.         }
  31.    
  32.         return 0;
  33. }/*END OF main()*/
复制代码

是偶尔几次得到的,我也不知为什么,有时得到的全部汇编代码为:
  1. 1:
  2. 2:
  3. 3:    #include <stdio.h>;
  4. 4:
  5. 5:    int main(void)
  6. 6:    {
  7. 0040E9C0   push        ebp
  8. 0040E9C1   mov         ebp,esp
  9. 0040E9C3   sub         esp,44h
  10. 0040E9C6   push        ebx
  11. 0040E9C7   push        esi
  12. 0040E9C8   push        edi
  13. 0040E9C9   lea         edi,[ebp-44h]
  14. 0040E9CC   mov         ecx,11h
  15. 0040E9D1   mov         eax,0CCCCCCCCh
  16. 0040E9D6   rep stos    dword ptr [edi]
  17. 7:        float x = (float)1e-3;
  18. 0040E9D8   mov         dword ptr [ebp-4],3A83126Fh
  19. 8:
  20. 9:        x = x + 1;
  21. 0040E9DF   fld         dword ptr [ebp-4]
  22. 0040E9E2   fadd        dword ptr [string "x is equal to x!" (0042401c)]
  23. 0040E9E8   fstp        dword ptr [ebp-4]
  24. 10:       printf("HELLO WORLD!\n");
  25. 0040E9EB   push        offset string "x = %f\n" (00425000)
  26. 0040E9F0   call        printf (00401090)
  27. 0040E9F5   add         esp,4
  28. 11:       //printf("x = %f\n", x);
  29. 12:       //printf("x != x is %d\n", (x != x));
  30. 13:       if (x != x)
  31. 0040E9F8   fld         dword ptr [ebp-4]
  32. 0040E9FB   fcomp       dword ptr [ebp-4]
  33. 0040E9FE   fnstsw      ax
  34. 0040EA00   test        ah,40h
  35. 0040EA03   jne         main+54h (0040ea14)
  36. 14:       {
  37. 15:           printf("x is UNequal to x!!\n");
  38. 0040EA05   push        offset string "x is unequal to x!!\n" (00424030)
  39. 0040EA0A   call        printf (00401090)
  40. 0040EA0F   add         esp,4
  41. 16:           //printf("x != x is %d\n", (x != x));
  42. 17:       }
  43. 18:       else
  44. 0040EA12   jmp         main+61h (0040ea21)
  45. 19:       {
  46. 20:           printf("x is equal to x!\n");
  47. 0040EA14   push        offset string "x is equal to x!\n" (00425018)
  48. 0040EA19   call        printf (00401090)
  49. 0040EA1E   add         esp,4
  50. 21:       }
  51. 22:       //printf("x != x is %d\n", (x != x));
  52. 23:
  53. 24:       return 0;
  54. 0040EA21   xor         eax,eax
  55. 25:   }
  56. 0040EA23   pop         edi
  57. 0040EA24   pop         esi
  58. 0040EA25   pop         ebx
  59. 0040EA26   add         esp,44h
  60. 0040EA29   cmp         ebp,esp
  61. 0040EA2B   call        __chkesp (004011c0)
  62. 0040EA30   mov         esp,ebp
  63. 0040EA32   pop         ebp
  64. 0040EA33   ret
复制代码

有时候又是:
  1. 1:    /***********************************************
  2. 2:    *file name   : float_accuracy.c
  3. 3:    *description : x是float类型,什么情况下x!=x为真
  4. 4:    *note        : 若在判断x!=x前对x进行了访问,
  5. 5:                   则有可能使x!=x为真
  6. 6:    *author      : kernelxu
  7. 7:    *resource    : http://bbs.chinaunix.net/forum/
  8. 8:                  viewtopic.php?t=575049&show_type=
  9. 9:    *date        : 2005/07/10
  10. 10:   ***********************************************/
  11. 11:
  12. 12:   #include <stdio.h>;
  13. 13:
  14. 14:   /**********************************************
  15. 15:   *function name :    main()
  16. 16:   ***********************************************/
  17. 17:   int main(void)
  18. 18:   {
  19. 0040E9C0   push        ebp
  20. 0040E9C1   mov         ebp,esp
  21. 0040E9C3   sub         esp,44h
  22. 0040E9C6   push        ebx
  23. 0040E9C7   push        esi
  24. 0040E9C8   push        edi
  25. 0040E9C9   lea         edi,[ebp-44h]
  26. 0040E9CC   mov         ecx,11h
  27. 0040E9D1   mov         eax,0CCCCCCCCh
  28. 0040E9D6   rep stos    dword ptr [edi]
  29. 19:       float x = (float)1e-3;
  30. 0040E9D8   mov         dword ptr [ebp-4],3A83126Fh
  31. 20:
  32. 21:       x = x + 1;
  33. 0040E9DF   fld         dword ptr [ebp-4]
  34. 0040E9E2   fadd        dword ptr [__real@4@3fff8000000000000000 (00425008)]
  35. 0040E9E8   fst         dword ptr [ebp-4]
  36. 22:       //printf("x = %f\n", x);
  37. 23:       //printf("x != x is %d\n", (x != x));
  38. 24:       if (x != x)
  39. 0040E9EB   fcomp       dword ptr [ebp-4]
  40. 0040E9EE   fnstsw      ax
  41. 0040E9F0   test        ah,40h
  42. 0040E9F3   jne         main+44h (0040ea04)
  43. 25:       {
  44. 26:           printf("x is UNequal to x!!\n");
  45. 0040E9F5   push        offset string "x != x is %d\n" (00425020)
  46. 0040E9FA   call        printf (00401090)
  47. 0040E9FF   add         esp,4
  48. 27:           //printf("x != x is %d\n", (x != x));
  49. 28:       }
  50. 29:       else
  51. 0040EA02   jmp         main+51h (0040ea11)
  52. 30:       {
  53. 31:           printf("x is equal to x!\n");
  54. 0040EA04   push        offset string "x != x is %d\n" (0042401c)
  55. 0040EA09   call        printf (00401090)
  56. 0040EA0E   add         esp,4
  57. 32:           //printf("x != x is %d\n", (x != x));
  58. 33:       }
  59. 34:
  60. 35:       return 0;
  61. 0040EA11   xor         eax,eax
  62. 36:   }/*END OF main()*/
  63. 0040EA13   pop         edi
  64. 0040EA14   pop         esi
  65. 0040EA15   pop         ebx
  66. 0040EA16   add         esp,44h
  67. 0040EA19   cmp         ebp,esp
  68. 0040EA1B   call        __chkesp (004011c0)
  69. 0040EA20   mov         esp,ebp
  70. 0040EA22   pop         ebp
  71. 0040EA23   ret
复制代码

搞不清啊?大家可以研究一下!

论坛徽章:
0
9 [报告]
发表于 2005-07-11 22:41 |只看该作者

请问x是float类型,什么情况下x!=x为真

x!=x, 这是不可能的。其值永远为 0。

论坛徽章:
0
10 [报告]
发表于 2005-07-12 10:20 |只看该作者

请问x是float类型,什么情况下x!=x为真

刚才请mq110兄在linux环境下试了一下第一例,结果是:
x is equal to x!

自己在TC2.0下试的结果是:
x is equal to x!

只有VC6.0(我用的是盗版的创天中文版,WIN2000 OS)下的结果是:
x is UNequal to x!!

所以该问题应该是编译器导致的,或许是VC的一个BUG,有VC的朋友试试,看看结果如何,不妨告知我一下。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP