float value = 1.9F;
value *= 10;
int temp = (int)(value + 700);double value = 1.9F;
int temp = (int)(value * 10 + 700);请高手指教一下,上面两段代码,temp的结果为什么不一样,前者为719,后者为718

解决方案 »

  1.   

    double 这个类型的问题,你可以在网上找找有解决方案
      

  2.   

    这是精度问题。float和double的问题
      

  3.   

    注明一下,这不是double型和float型的区别,因为用float型的也一样。
      

  4.   

    这是精度问题。float和double的问题,高低位转换时会丢失精度的。
      

  5.   

    应该比较好理解,double的精度范围±5.0 × 10^-324 到 ±1.7 × 10^308
    当声明double value = 1.9F;时候,其实value的值是1.89999999...这个通过调试可以看到
    知道这个下面就好理解了value * 10 自动转换为int型得18
      

  6.   


    float 是单精度的
    double是双精度的
    你断点一下就知道了
      

  7.   

    1.9不是一个能无损表示的浮点数。double 有52个有效位,1.9F * 10 有效位可以表示为1 .0010111111111111111111111100000000000000000000000000但是float只有23有效位,1.9F * 10 有效位必须截断进位表示为 1 .00110000000000000000000。
    二者的指数位都是 ×16,所以 float结果反而达到了19
      

  8.   

    说错了,这个时候是不转换的,(int)的时候转换的
      

  9.   

    float value = 1.9F;
    value *= 10;//此时value 为19
    int temp = (int)(value + 700);double value = 1.9F;//value为1.9f
    int temp = (int)(value * 10 + 700);//乘10后为18.99999..
      

  10.   

    1.9F 表示float  而你定义的double
    精度丢失
      

  11.   

    首先我要说的是,这确实是一个精度的问题,但是这不是double和float之间的问题(就这个问题而言)。其次即使你把上面代码中的double换成float效果是一样的,你用一个宽的表示一个窄的这不会有问题的,理论上来说精度更高了。最后分析一下这个问题,先说说他们生成的IL代码,差异只有一句话就是在求值以后将值赋给value然后再压入求值栈求值,有兴趣的可以看看他们的代码之间的差异,这里我不描述了。下面我从汇编角度来分析一下为什么会是这种结果(其实求值栈的问题我也没想明白,为什么看着只是取出来又放回去就不一样了呢?)。下面是这两段代码的汇编指令:0000003a  mov         dword ptr [ebp-40h],3FF33333h ; 将1.9F保存在栈上的局部变量里面
    00000041  fld         dword ptr [ebp-40h]           ; 将1.9F装入浮点寄存器ST0
    00000044  fmul        dword ptr ds:[0050156Ch]      ; 将浮点寄存器ST0里面的乘以10保存到ST0里面
    0000004a  sub         esp,8                         ; 调整栈指针
    0000004d  fstp        qword ptr [esp]               ; 将ST0里面的值放到栈顶作为调用716E133C的参数
    00000050  call        716E133C                      ; 调用转换函数
    ============================================================================
    0000003a  mov         dword ptr [ebp-40h],3FF33333h ; 将1.9F保存在栈上的局部变量里面
    00000041  fld         dword ptr ds:[00571570h]      ; 将1.9F装入浮点寄存器ST0
    00000047  fmul        dword ptr [ebp-40h]           ; ST0*ebp-40h保存到ST0里面
    0000004a  fstp        dword ptr [ebp-40h]           ; 将ST0的值保存在ebp-40的位置
    0000004d  fld         dword ptr [ebp-40h]           ; 将这个ebp-40h上的浮点取出来放到ST0里面
    00000050  sub         esp,8                         ; 调整栈指针
    00000053  fstp        qword ptr [esp]               ; 将ST0里面的值放到栈顶作为调用7167133C的参数
    00000056  call        7167133C                      ; 调用转换函数可以看出问题就在红色的这两句(貌似和IL是一致的),实际上float在浮点寄存器的里面的值是: +1.8999999761581420e+0001,但是当保存到栈上再取出来以后就变成了+1.9000000000000000e+0001,这里存在一个“隐式转换”。显然正确的结果应该是19而不是18,通过上面的分析,程序稍加修改便可以得到正确的输出结果:
    int temp = (int)((float)(value2 * 10 + 700));
    再转整形之前将求值内容转换成float即可。
    个人意见,仅供参考。
      

  12.   

    从源头上避免误差            double value2 = double.Parse(1.9F.ToString());
                int temp2 = (int)(value2 * 10 + 700);