还是浮点数的问题

搬板砖 2015-09-05 08:34:31
一个浮点数每次加0.01,一直加到0.13,再减0.01,减到0.01,再减一次0.01,理论应该是0,可实际并不是

void float_mem_short(float src_vlaue, unsigned short *fshort)
{
fshort[0] = *(unsigned short *)&src_vlaue;
fshort[1] = *((unsigned short *)&src_vlaue + 1);
}
int main()
{
float ff = 0;
unsigned short u_f[2];

for (; ff < 0.13; ff+=0.01)
{
float_mem_short(ff, u_f);
printf("%f %04x %04x\n", ff, u_f[0], u_f[1]);
}
for (; ff >= 0; ff-=0.01)
{
float_mem_short(ff, u_f);
printf("%e %04x %04x\n", ff, u_f[0], u_f[1]);
}


结果:
0.000000 0000 0000
0.010000 d70a 3c23
0.020000 d70a 3ca3
0.030000 c28f 3cf5
0.040000 d70a 3d23
0.050000 cccd 3d4c
0.060000 c290 3d75
0.070000 5c29 3d8f
0.080000 d70a 3da3
0.090000 51eb 3db8
0.100000 cccc 3dcc
0.110000 47ad 3de1
0.120000 c28e 3df5
0.130000 1eb8 3e05
1.400000e-001 5c29 3e0f
1.300000e-001 1eb8 3e05
1.200000e-001 c28f 3df5
1.100000e-001 47ae 3de1
1.000000e-001 cccd 3dcc
9.000000e-002 51ec 3db8
8.000001e-002 d70b 3da3
7.000001e-002 5c2a 3d8f
6.000001e-002 c291 3d75
5.000000e-002 ccce 3d4c
4.000000e-002 d70b 3d23
3.000000e-002 c291 3cf5
2.000000e-002 d70c 3ca3
1.000000e-002 d70e 3c23
3.501773e-009 a3d7 3170

注意上面红色的部分。
如果往上加,只加到0.12,再往回减,则不会出现3.501773e-009 a3d7 3170
如何解决这个问题???
...全文
147 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
paschen 2015-09-06
  • 打赏
  • 举报
回复
十进制的浮点数有些是不能用二进制精确表示的,是会存在误差,可以试下用double,甚至long double,通常能满足精度要求 如果需要超高精确度的计算, 可以使用BCD代码(Binary-Coded Decimal‎)
xian_wwq 2015-09-06
  • 打赏
  • 举报
回复
float类型有效位数也就7位 要求太高了,达不到
赵4老师 2015-09-06
  • 打赏
  • 举报
回复
仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
float f;
double d;
void showf() {
    char bs[65];
    char b[65];
    unsigned char *p;
    char e[12];
    char *t;
    int ex;

    printf("\nf=%.6f\n",f);
    p=(unsigned char *)&f;
    printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);
    ltoa(*(long *)&f,b,2);
    sprintf(bs,"%032s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);
    strncpy(e,bs+1,8);e[8]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);
    ex-=127;
    printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);
}
void showd() {
    char bs[65];
    char b[65];
    unsigned char *p;
    char e[12];
    char *t;
    int ex;

    printf("\nd=%.15lf\n",d);
    p=(unsigned char *)&d;
    printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);
    _i64toa(*(__int64 *)&d,b,2);
    sprintf(bs,"%064s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);
    strncpy(e,bs+1,11);e[11]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);
    ex-=1023;
    printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);
}
int main() {

    for (f=0.0f;f<=2.2f;f+=0.2f) showf();
    printf("------------\n");
    f=2.0f;showf();
    printf("-----------------------------------\n");
    for (d=0.0 ;d<=2.2 ;d+=0.2 ) showd();
    printf("------------\n");
    d=2.0 ;showd();

    return 0;
}
//
//f=0.000000
//hex=00 00 00 00
//bin=00000000000000000000000000000000
//bin=0 00000000   00000000000000000000000
//  + 0   -127 1.00000000000000000000000
//  + -127     1.00000000000000000000000
//
//f=0.200000
//hex=3E 4C CC CD
//bin=00111110010011001100110011001101
//bin=0 01111100   10011001100110011001101
//  + 124 -127 1.10011001100110011001101
//  + -3       1.10011001100110011001101
//
//f=0.400000
//hex=3E CC CC CD
//bin=00111110110011001100110011001101
//bin=0 01111101   10011001100110011001101
//  + 125 -127 1.10011001100110011001101
//  + -2       1.10011001100110011001101
//
//f=0.600000
//hex=3F 19 99 9A
//bin=00111111000110011001100110011010
//bin=0 01111110   00110011001100110011010
//  + 126 -127 1.00110011001100110011010
//  + -1       1.00110011001100110011010
//
//f=0.800000
//hex=3F 4C CC CD
//bin=00111111010011001100110011001101
//bin=0 01111110   10011001100110011001101
//  + 126 -127 1.10011001100110011001101
//  + -1       1.10011001100110011001101
//
//f=1.000000
//hex=3F 80 00 00
//bin=00111111100000000000000000000000
//bin=0 01111111   00000000000000000000000
//  + 127 -127 1.00000000000000000000000
//  + 0        1.00000000000000000000000
//
//f=1.200000
//hex=3F 99 99 9A
//bin=00111111100110011001100110011010
//bin=0 01111111   00110011001100110011010
//  + 127 -127 1.00110011001100110011010
//  + 0        1.00110011001100110011010
//
//f=1.400000
//hex=3F B3 33 34
//bin=00111111101100110011001100110100
//bin=0 01111111   01100110011001100110100
//  + 127 -127 1.01100110011001100110100
//  + 0        1.01100110011001100110100
//
//f=1.600000
//hex=3F CC CC CE
//bin=00111111110011001100110011001110
//bin=0 01111111   10011001100110011001110
//  + 127 -127 1.10011001100110011001110
//  + 0        1.10011001100110011001110
//
//f=1.800000
//hex=3F E6 66 68
//bin=00111111111001100110011001101000
//bin=0 01111111   11001100110011001101000
//  + 127 -127 1.11001100110011001101000
//  + 0        1.11001100110011001101000
//
//f=2.000000
//hex=40 00 00 01
//bin=01000000000000000000000000000001
//bin=0 10000000   00000000000000000000001
//  + 128 -127 1.00000000000000000000001
//  + 1        1.00000000000000000000001
//------------
//
//f=2.000000
//hex=40 00 00 00
//bin=01000000000000000000000000000000
//bin=0 10000000   00000000000000000000000
//  + 128 -127 1.00000000000000000000000
//  + 1        1.00000000000000000000000
//-----------------------------------
//
//d=0.000000000000000
//hex=00 00 00 00 00 00 00 00
//bin=0000000000000000000000000000000000000000000000000000000000000000
//bin=0 00000000000   0000000000000000000000000000000000000000000000000000
//  + 0     -1023 1.0000000000000000000000000000000000000000000000000000
//  + -1023       1.0000000000000000000000000000000000000000000000000000
//
//d=0.200000000000000
//hex=3F C9 99 99 99 99 99 9A
//bin=0011111111001001100110011001100110011001100110011001100110011010
//bin=0 01111111100   1001100110011001100110011001100110011001100110011010
//  + 1020  -1023 1.1001100110011001100110011001100110011001100110011010
//  + -3          1.1001100110011001100110011001100110011001100110011010
//
//d=0.400000000000000
//hex=3F D9 99 99 99 99 99 9A
//bin=0011111111011001100110011001100110011001100110011001100110011010
//bin=0 01111111101   1001100110011001100110011001100110011001100110011010
//  + 1021  -1023 1.1001100110011001100110011001100110011001100110011010
//  + -2          1.1001100110011001100110011001100110011001100110011010
//
//d=0.600000000000000
//hex=3F E3 33 33 33 33 33 34
//bin=0011111111100011001100110011001100110011001100110011001100110100
//bin=0 01111111110   0011001100110011001100110011001100110011001100110100
//  + 1022  -1023 1.0011001100110011001100110011001100110011001100110100
//  + -1          1.0011001100110011001100110011001100110011001100110100
//
//d=0.800000000000000
//hex=3F E9 99 99 99 99 99 9A
//bin=0011111111101001100110011001100110011001100110011001100110011010
//bin=0 01111111110   1001100110011001100110011001100110011001100110011010
//  + 1022  -1023 1.1001100110011001100110011001100110011001100110011010
//  + -1          1.1001100110011001100110011001100110011001100110011010
//
//d=1.000000000000000
//hex=3F F0 00 00 00 00 00 00
//bin=0011111111110000000000000000000000000000000000000000000000000000
//bin=0 01111111111   0000000000000000000000000000000000000000000000000000
//  + 1023  -1023 1.0000000000000000000000000000000000000000000000000000
//  + 0           1.0000000000000000000000000000000000000000000000000000
//
//d=1.200000000000000
//hex=3F F3 33 33 33 33 33 33
//bin=0011111111110011001100110011001100110011001100110011001100110011
//bin=0 01111111111   0011001100110011001100110011001100110011001100110011
//  + 1023  -1023 1.0011001100110011001100110011001100110011001100110011
//  + 0           1.0011001100110011001100110011001100110011001100110011
//
//d=1.400000000000000
//hex=3F F6 66 66 66 66 66 66
//bin=0011111111110110011001100110011001100110011001100110011001100110
//bin=0 01111111111   0110011001100110011001100110011001100110011001100110
//  + 1023  -1023 1.0110011001100110011001100110011001100110011001100110
//  + 0           1.0110011001100110011001100110011001100110011001100110
//
//d=1.600000000000000
//hex=3F F9 99 99 99 99 99 99
//bin=0011111111111001100110011001100110011001100110011001100110011001
//bin=0 01111111111   1001100110011001100110011001100110011001100110011001
//  + 1023  -1023 1.1001100110011001100110011001100110011001100110011001
//  + 0           1.1001100110011001100110011001100110011001100110011001
//
//d=1.800000000000000
//hex=3F FC CC CC CC CC CC CC
//bin=0011111111111100110011001100110011001100110011001100110011001100
//bin=0 01111111111   1100110011001100110011001100110011001100110011001100
//  + 1023  -1023 1.1100110011001100110011001100110011001100110011001100
//  + 0           1.1100110011001100110011001100110011001100110011001100
//
//d=2.000000000000000
//hex=3F FF FF FF FF FF FF FF
//bin=0011111111111111111111111111111111111111111111111111111111111111
//bin=0 01111111111   1111111111111111111111111111111111111111111111111111
//  + 1023  -1023 1.1111111111111111111111111111111111111111111111111111
//  + 0           1.1111111111111111111111111111111111111111111111111111
//
//d=2.200000000000000
//hex=40 01 99 99 99 99 99 99
//bin=0100000000000001100110011001100110011001100110011001100110011001
//bin=0 10000000000   0001100110011001100110011001100110011001100110011001
//  + 1024  -1023 1.0001100110011001100110011001100110011001100110011001
//  + 1           1.0001100110011001100110011001100110011001100110011001
//------------
//
//d=2.000000000000000
//hex=40 00 00 00 00 00 00 00
//bin=0100000000000000000000000000000000000000000000000000000000000000
//bin=0 10000000000   0000000000000000000000000000000000000000000000000000
//  + 1024  -1023 1.0000000000000000000000000000000000000000000000000000
//  + 1           1.0000000000000000000000000000000000000000000000000000
//
宋寒松 2015-09-05
  • 打赏
  • 举报
回复
3.501773e-009已经足够小,就是你所谓的0.0了。浮点数与0的比较实际上是一个值的绝对值趋向无穷小,例如:

#define EPS (0.0000001)
if(fabs(a) < EPS){
  ...
}

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧