|
在做Win32平台下的文本文件转二进制文件的CLI小程序时发现一个意外。
代码片段:
float f;
short s;
while(fscanf(in_file, "%f", &f) != EOF)
{
if(fabs(f) < ((1 << 15) / 10))
{
f *= 10;
s = (short)f;
}
else
s = 0x7fff;
}
将其改为如下后跟原来的s值有个别不一样:
float f;
short s;
while(fscanf(in_file, "%f", &f) != EOF)
{
if(fabs(f) < ((1 << 15) / 10))
{
s = (short)(f * 10);
}
else
s = 0x7fff;
}
然后单独写个测试程序测试下,发现其实会不一样:
#include <stdio.h>
int main(int argc, char **argv)
{
float f;
short s1, s2;
printf("输入浮点数:\n");
scanf("%f", &f);
s1 = (short)(f * 10);
f *= 10;
s2 = (short)f;
printf("s1 %s s2\n", (s1 == s2)? "==" : "!=");
printf("s1 = %d, s2 = %d\n", s1, s2);
return 0;
}
输出:
输入浮点数:
1.9
s1 != s2
s1 = 18, s2 = 19
当输入值的小数位为.95以下时不一样,即两者的舍入误差不一样。
下面是其对应的汇编代码:
main:
0040138c: push %ebp
0040138d: mov %esp,%ebp
0040138f: and $0xfffffff0,%esp
00401392: sub $0x30,%esp
159 {
00401395: call 0x40196c <__main>
163 printf("输入浮点数:\n");
0040139a: movl $0x403064,(%esp)
004013a1: call 0x401ba4 <puts>
164 scanf("%f", &f);
004013a6: lea 0x28(%esp),%eax
004013aa: mov %eax,0x4(%esp)
004013ae: movl $0x403070,(%esp)
004013b5: call 0x401bac <scanf>
166 s1 = (short)(f * 10);
004013ba: flds 0x28(%esp)
004013be: flds 0x403098
004013c4: fmulp %st,%st(1)
004013c6: fnstcw 0x1e(%esp)
004013ca: mov 0x1e(%esp),%ax
004013cf: mov $0xc,%ah
004013d1: mov %ax,0x1c(%esp)
004013d6: fldcw 0x1c(%esp)
004013da: fistp 0x2e(%esp)
004013de: fldcw 0x1e(%esp)
167 f *= 10;
004013e2: flds 0x28(%esp)
004013e6: flds 0x403098
004013ec: fmulp %st,%st(1)
004013ee: fstps 0x28(%esp)
168 s2 = (short)f;
004013f2: flds 0x28(%esp)
004013f6: fldcw 0x1c(%esp)
004013fa: fistp 0x2c(%esp)
004013fe: fldcw 0x1e(%esp)
169 printf("s1 %s s2\n", (s1 == s2)? "==" : "!=");
00401402: mov 0x2e(%esp),%ax
00401407: cmp 0x2c(%esp),%ax
0040140c: jne 0x401415 <main+137>
0040140e: mov $0x403073,%eax
00401413: jmp 0x40141a <main+142>
00401415: mov $0x403076,%eax
0040141a: mov %eax,0x4(%esp)
0040141e: movl $0x403079,(%esp)
00401425: call 0x401bb4 <printf>
170 printf("s1 = %d, s2 = %d\n", s1, s2);
0040142a: movswl 0x2c(%esp),%edx
0040142f: movswl 0x2e(%esp),%eax
00401434: mov %edx,0x8(%esp)
00401438: mov %eax,0x4(%esp)
0040143c: movl $0x403083,(%esp)
00401443: call 0x401bb4 <printf>
172 return 0;
00401448: mov $0x0,%eax
173 } |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|