解决方案 »

  1.   

    浮点数相乘会有精度误差,也就是有的时候结果略小于真实值,有时略大于。
    强制类型转换直接忽略尾数,所以当结果略小的时候,就会差1。而convert转换是四舍五入的。
    结论,不要用强制类型转换。
      

  2.   

    int a = 100;
    float b = 0.01f;
    int c = (int)(a * b);//结果0
    00972993  fild        dword ptr [ebp-40h]  32位浮点压栈
    00972996  fstp        dword ptr [ebp-94h]  32位浮点出栈     比double多出这一步
    0097299C  fld         dword ptr [ebp-94h]  再传入寄存器     比double多出这一步,说明是先将float要先转化成double再转化成int,根本原因就是这里             的转化出现了误差
    009729A2  fmul        dword ptr [ebp-44h]  乘法
    009729A5  fstp        qword ptr [ebp-9Ch]  弹出 64位浮点
    009729AB  movsd       xmm0,mmword ptr [ebp-9Ch]  将上面64位浮点传参
    009729B3  cvttsd2si   eax,xmm0                    强转浮点
    009729B7  mov         dword ptr [ebp-48h],eax  int ccc = Convert.ToInt32(a * b);//结果1
    009729C1  fild        dword ptr [ebp-40h]  
    009729C4  fstp        dword ptr [ebp-94h]  
    009729CA  fld         dword ptr [ebp-94h]  
    009729D0  fmul        dword ptr [ebp-44h]  
    009729D3  sub         esp,4  
    009729D6  fstp        dword ptr [esp]  
    009729D9  call        731167DC              关键这行调用了一个函数处理转化
    009729DE  mov         dword ptr [ebp-78h],eax  
    009729E1  mov         eax,dword ptr [ebp-78h]  
    009729E4  mov         dword ptr [ebp-50h],eax  
     int cc = (int)(100 * 0.01); // 这里的0.01默认是double类型
    009729F0  fild        dword ptr [ebp-40h]  这里几乎和float一样只少了32转64的步骤
    009729F3  fmul        qword ptr [ebp-58h]  
    009729F6  fstp        qword ptr [ebp-9Ch]  
    009729FC  movsd       xmm0,mmword ptr [ebp-9Ch]  
    00972A04  cvttsd2si   eax,xmm0  
    00972A08  mov         dword ptr [ebp-5Ch],eax  
      

  3.   

    0097299C  fld         dword ptr [ebp-94h]  再传入寄存器     比double多出这一步,说明是先将float要先转化成double再转化成int,根本原因就是这里,float转化成double导致的数据精度误差
      

  4.   

    你看一下int   falot,精确度,还有强制转换
      

  5.   

    是因为精度丢失引起的。
    根本原因是计算机是按照二进制来存储和处理数据的,有些小数变成二进制表示时会无限长,无法精确表示,所以就存在精度丢失的问题。int c = (int)(a * b);           //结果0 
    可以等效成: var j = (int) ((double) (a*b));   
    由于b你强制指定是float,这时候相当于将doubl转成float,会有精度丢失的可能。接着你(a*b)其实暗含将float转会double,因为之前已经有精度问题,所以这里数据已经不对,结果为0就可以解释了。
    你可以试一试:
    float b = 0.01f;
    var i = (double)b;
    看看此时的i是不是和原来的0.01不一样了。然后再看会那个等效的语句。
    int cc=(int)(100*0.01);  结果1
    因为C#里0.01就是double型(默认小数是这个数据类型),不存在float和double转换时精度丢失的问题。
      

  6.   

    LZ什么运行环境?
    我运行的结果c就是1。