回复 20楼 cosdos
嗯,也有这种可能
重剑无锋,大巧不工
; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.61030.0 TITLE D:\Projects\test\Project9\Project9\main.cpp .686P .XMM include listing.inc .model flat INCLUDELIB MSVCRTD INCLUDELIB OLDNAMES PUBLIC _main PUBLIC ??_C@_05LCCCBGPN@True?6?$AA@ ; `string' EXTRN __imp__printf_s:PROC EXTRN __imp___getch:PROC EXTRN __RTC_CheckEsp:PROC EXTRN __RTC_InitBase:PROC EXTRN __RTC_Shutdown:PROC EXTRN __fltused:DWORD ; COMDAT rtc$TMZ rtc$TMZ SEGMENT __RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown rtc$TMZ ENDS ; COMDAT rtc$IMZ rtc$IMZ SEGMENT __RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase rtc$IMZ ENDS ; COMDAT ??_C@_05LCCCBGPN@True?6?$AA@ CONST SEGMENT ??_C@_05LCCCBGPN@True?6?$AA@ DB 'True', 0aH, 00H ; `string' CONST ENDS ; Function compile flags: /Odtp /RTCsu /ZI ; File d:\projects\test\project9\project9\main.cpp ; COMDAT _main _TEXT SEGMENT _n$ = -8 ; size = 4 _main PROC ; COMDAT ; 5 : { push ebp mov ebp, esp sub esp, 204 ; 000000ccH push ebx push esi push edi lea edi, DWORD PTR [ebp-204] mov ecx, 51 ; 00000033H mov eax, -858993460 ; ccccccccH rep stosd ; 6 : int n = 0x80000000; mov DWORD PTR _n$[ebp], -2147483648 ; 80000000H ; 7 : ; 8 : if (n == (int)(float) n) cvtsi2ss xmm0, DWORD PTR _n$[ebp] cvttss2si eax, xmm0 cmp DWORD PTR _n$[ebp], eax jne SHORT $LN1@main ; 9 : { ; 10 : printf_s("True\n"); mov esi, esp push OFFSET ??_C@_05LCCCBGPN@True?6?$AA@ call DWORD PTR __imp__printf_s add esp, 4 cmp esi, esp call __RTC_CheckEsp $LN1@main: ; 11 : } ; 12 : _getch(); mov esi, esp call DWORD PTR __imp___getch cmp esi, esp call __RTC_CheckEsp ; 13 : } xor eax, eax pop edi pop esi pop ebx add esp, 204 ; 000000ccH cmp ebp, esp call __RTC_CheckEsp mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS END
#include <stdio.h> //精度损失 void demo1( ) { int n = 0; float f = n ; // float f = n ;汇编代码 // fild DWORD PTR _n$[ebp] ;把n的值放到浮点寄存器( 80位 ), 远大于 32bits,精度无损 // fstp DWORD PTR _f$[ebp] ;这里把浮点寄存器( 80位 )的值返回到变量f( 32位 ),造成精度损失 // 原因:float变量内存结构:1bit(符号位) 8bits(指数位) 23bits(尾数位) // 当 n有效位 > 24bits 时,尾数丢失 if (n==(int)f) //上面 n = 0; n< 24bits, 因此精度无损,输出TRUE printf("TRUE\n"); else printf("Flase\n"); n = 0x1ffffff ;//这里 n为25bits , 且超出24bits部分不为0 f = n ; if (n==(int)f) //这里 n为25bits , n> 24bits, 因此精度丢失,输出Flase printf("TRUE\n"); else printf("Flase\n"); n = 0x1fffff0 ;//这里 n为25bits , 且最后4bit为0 , 丢失后与丢失前相同(都是零) f = n ; if (n==(int)f) // 因此精度丢失,但丢失前后相同,输出TRUE printf("TRUE\n"); else printf("Flase\n"); } //精度无损 void demo2( ) { int n; if (n==(int)(float)n) //反汇编代码 //fild DWORD PTR _n$[ebp] ;把n的值放到浮点寄存器( 80位 ), 远大于 32bits,精度无损 // call __ftol ;把浮点寄存器的值放到eax , 精度无损,原因:eax就是无符号整型 // cmp DWORD PTR _n$[ebp], eax ;将n的值与eax比较,恒相等。 printf("TRUE"); //输出True else printf("Flase"); } int main( ) { demo1( ); demo2( ); return 0; }测试结果:TRUE FALSE TRUE TRUE
#include <stdio.h> int main( ) { //恒输出TRUE int n; if (n==(int)(float)n) printf("TRUE\n"); else printf("False\n"); //三种情况 //1. n<0x1000001 时 , 转化为浮点数时没有丢失精度,程序输出TRUE n = 5 ; float f = n ; if (n==(int)f) printf("TRUE\n"); else printf("False\n"); // 2. n>=0x1000001 时 ,可以分两种情况 // 2.1 从左往右数24位,大于24位的将被抛弃。 // 如果被抛弃的都是0 ,则抛弃前后没有影响,因为还原后还是0 , 程序输出TRUE n = 0x1000010 ; f = n ; if (n==(int)f) printf("TRUE\n"); else printf("False\n"); // 2.2 如果被抛弃的数据中含有1 ,则因为还原后都是0 , // 所以造成n的低位与(int)f的低位不相等,程序输出False。 n = 0x1000001 ; f = n ; if (n==(int)f) printf("TRUE\n"); else printf("False\n"); return 0; }