请各位大哥帮帮我吧
分析分析是什么原因引起二种方法结果不相同float k1;
int k;//方法一
k1=4.6f;
k1 =(int)(k1 * 10);
MessageBox.Show(k+"");  //显示结果为45//方法二
k1=4.6f;
k1 = (k1 * 10);
k = (int)k1;
MessageBox.Show(k+"");  //显示结果为46

解决方案 »

  1.   

    第一个MessageBox.Show(k+"");  //显示结果为45
    应该是MessageBox.Show(k1+""); 吗
      

  2.   

    float k1=4.6f;            k1 =k1 * 10;            int k = (int)k1;
                MessageBox.Show(k.ToString());
    没问题了,46
      

  3.   

    Ivony() 浮点数不能用作精确运算,出现这样的误差纯属正常……
    也可以理解,不过为什么一步会出错,就二步就没问题呢,一步到位:k1 =(int)(k1 * 10);
    二步实现:k1 = (k1 * 10);
              k = (int)k1;
      

  4.   

    打错了,不好意思
    一步到位:k  =(int)(k1 * 10);
    二步实现:k1 = (k1 * 10);
              k = (int)k1;
      

  5.   

    不怪.大家认为 Math.Round(2.50,0) = ?答对了,微软请客!
      

  6.   

    Math.Round(2.50,0) = 
    如果精确,应当返回 2.0000000~ (向偶数舍入)
    如果因为精度问题 2.50稍微大了一点,3.000000~ 
    如果小了一点,2.000000~
      

  7.   

    看来各位还没完全理解我的意思
    我是想问为什么结果会不一样
    是进行的一样的操作啊一步到位:k  =(int)(k1 * 10);   //结果K等于45,这个就算是精度问题
    二步实现:k1 = (k1 * 10);
              k = (int)k1;          //结果K等于46,这个和上一种方法有什么不同吗,只不过是把一句写成了二句,结果应该一样啊
      

  8.   

    强制转换最好换成标准的转换方法 Convert.ToInt32 ,这样结果就都是46了
      

  9.   

    从float型向int转化的时候出现溢出问题
      

  10.   

    checked过
    没有发现溢出 10改为7、8或者11这样都是一样的
      

  11.   

    同意:加(int)后运算顺序不同了。
      

  12.   

    float k1=4.6f float类型的变量存储的是它的近似值,应该是4.55555555什么之类的(比如是8位)
    而//方法一
    k1=4.6f;
    k1 =(int)(k1 * 10);k1*10之后是45.55555 然后在类型转换 当然是45了
    MessageBox.Show(k+"");  //显示结果为45//方法二
    k1=4.6f;
    k1 = (k1 * 10); 
    k = (int)k1;
    MessageBox.Show(k+"");  //显示结果为46
    主要看数据类型的精度和在内存中的存储原理
      

  13.   

    我明白你的意思,不过这个问题的确奇怪,我也不知道。事实上(k1 * 10)会自动把10从int转换成float来计算,所以结果本来就是float,存到一个float型的变量中再(int)或者直接(int)应该结果是一样的。
      

  14.   

    to:nayc(nayc) 
    float k1=4.6f float类型的变量存储的是它的近似值,应该是4.55555555什么之类的(比如是8位)
    按你的说法 类型转化会四舍五入才对 为什么是45?
      

  15.   

    k =(int)(k1 * 10);k1*10之后是45.999999 然后在类型转换 当然是45了
    k1 = (k1 * 10); k1*10之后是45.999999 然后在赋值给k1,k1的值是46
    k = (int)k1;   对k1进行强制int转换后,取整46
    所以输出结果出现不同
      

  16.   

    经测试用4.7f,4.8f,4.4f,4.5f及用k1*5
    发现4.7>46  ,4.8>48,4.5>45
    k1*5时4.2〉21,4.8〉29
    得出结论:尾数为0,3,4,5,8,9时存为n+0.000000000000001
    尾数为1,2,6,7时存为n-0.00000000000000000001。(n为尾数)
    等大家检验 。
      

  17.   

    to zhousheng198 (海)  & nayc(nayc) float/double 到 int 的类型转换不是四舍五入,也不是其它的舍入操作,而是截断小数点后面的部分。所以 (int)45.999999999999  = 45;根据测试,如果直接输出 Console.WriteLine(4.6 * 10); 是 46;
    也就是说,浮点运算之后得到的结果如果赋值给浮点数或者以浮点方式处理(自动或人为指定的),则能够保证精度(当然不能是绝对的精确),如果进行 float 到 int 的强制转换操作则会直接截断小数点后面的部分(小数点后面的数被抛弃了),故如果是  X.99999999999 就是产生严重误差。
      

  18.   

    这个问题跟K1,K2的数据类型有关。
    float k1;
    int k;
    请注意你的定义,k1为float,k为int
    当执行k=(int)(k1 * 10);时,由于k为int,10会作int处理,会自动先把k1进行转换(由于变量类型的字节数不同,造成转换溢出),然后与10进行运算,最后的结果造成误差。而
    k1 = (k1 * 10); 
    因K1是float,这时会把10示作float类型,不用转换k1后再运算,不会造成溢出误差,其结果是46.0,当把46.0转成整数时,不会造成去尾丢失,所以结果是46.这说明了一个问题,当一个变量和一个像10这个无法直接识别为何数据类型的常数(10可以是int,也可以是float,也可以是double,你说10是什么类型呢?无法确定)进行运算时,系统会先对它们进行类型转换,把它们转成相同类型后再进行运算,到底对哪个进行转换,示目标变量的类型而定.你可以这样测试:
    k  =(int)(k1 * (float)10); 
    或k  =(int)(k1 * 10.0); 大家说结果会是多少呢?
    说对了就来我们微软工作吧!
      

  19.   

    k  =(int)(k1 * 10.0);  还是45
    刚看楼主的贴子9测试过了 
      

  20.   

    这个问题跟K1,K2的数据类型有关。
    float k1;
    int k;
    请注意你的定义,k1为float,k为int
    当执行k=(int)(k1 * 10);时,由于k为int,10会作int处理,会自动先把k1进行转换(由于变量类型的字节数不同,造成转换溢出),然后与10进行运算,最后的结果造成误差。而
    k1 = (k1 * 10); 
    因K1是float,这时会把10示作float类型,不用转换k1后再运算,不会造成溢出误差,其结果是46.0,当把46.0转成整数时,不会造成去尾丢失,所以结果是46.这说明了一个问题,当一个变量和一个像10这个无法直接识别为何数据类型的常数(10可以是int,也可以是float,也可以是double,你说10是什么类型呢?无法确定)进行运算时,系统会先对它们进行类型转换,把它们转成相同类型后再进行运算,到底对哪个进行转换,示目标变量的类型而定.你可以这样测试:
    k  =(int)(k1 * (float)10); 
    或k  =(int)(k1 * 10.0); 大家说结果会是多少呢?
    说对了就来我们微软工作吧!============================================================程序员最忌讳的就是想当然……当执行k=(int)(k1 * 10);时,由于k为int,10会作int处理,会自动先把k1进行转换(由于变量类型的字节数不同,造成转换溢出),然后与10进行运算,最后的结果造成误差。这个纯粹就是胡说八道……
    当一个浮点型的数字乘以整型的数字的时候,会自动把整型的转换成浮点型。一般来说:int * int = int;
    long * long = long;
    long * int = int * long = long;
    float * int = int * float = float;
    float * float = float;
    double * float = float * double = double;而不可能是将浮点型转换成整型,然后按整型计算乘法。你自己一试便知:
    float f = 5;
    iny k = f * 10;//编译错误,这里需要强制类型转换,因为后面的表达式是浮点型的。
    至于这个:k  =(int)(k1 * (float)10); 
    或k  =(int)(k1 * 10.0); 你根本就没搞清楚10.0是double!
      

  21.   

    我也知道会被骂的了!!
    我确实有没有看清楚就乱说。为消除影响,作下面的更正:附测试代码:float k1;
    k1=4.6f;this.Response.Write("1: "+k1.ToString("0.00000000000000000000000000")+"<br>");
    this.Response.Write("2: "+((double)k1).ToString("0.00000000000000000000000000")+"<br>");
    this.Response.Write("3: "+((k1*10)).ToString("0.0000000000000000000000000000000")+"<br>");
    this.Response.Write("4: "+((k1*10d)).ToString("0.0000000000000000000000000000000")+"<br>");
    this.Response.Write("5: "+((int)(k1*10)).ToString("0.00000000000000000000")+"<br>");
    this.Response.Write("6: "+((int)(k1*10f)).ToString("0.0000000000000000")+"<br>");
    this.Response.Write("7: "+((int)(float)(k1*10)).ToString("0.0000000000000000")+"<br>");
    this.Response.Write("8: "+((double)(float)(k1*10)).ToString("0.00000000000000000000000000")+"<br>");this.Response.Write("<br>");this.Response.Write("9: "+(k1-0.1).ToString("0.000000000000000000000")+"<br>");
    this.Response.Write("10: "+(k1-0.1f).ToString("0.000000000000000000000")+"<br>");
    this.Response.Write("11: "+((float)(k1-0.1)).ToString("0.0000000000000000000000")+"<br>");this.Response.Write("<br>");this.Response.Write("12: "+((int)(float)5.999999).ToString("0.00000000000000000000000000")+"<br>");
    this.Response.Write("13: "+((int)(float)5.9999999).ToString("0.00000000000000000000000000")+"<br>");
    this.Response.Write("14: "+((int)5.9999999).ToString("0.00000000000000000000000000")+"<br>");
    this.Response.Write("15: "+((double)(float)5.9999999).ToString("0.00000000000000000000000000")+"<br>");
    以上代码的运行结果:1: 4.60000000000000000000000000
    2: 4.59999990463257000000000000
    3: 46.0000000000000000000000000000000
    4: 45.9999990463257000000000000000000
    5: 45.00000000000000000000
    6: 45.0000000000000000
    7: 46.0000000000000000
    8: 46.000000000000000000000000009: 4.499999904632570000000
    10: 4.500000000000000000000
    11: 4.500000000000000000000012: 5.00000000000000000000000000
    13: 6.00000000000000000000000000
    14: 5.00000000000000000000000000
    15: 6.00000000000000000000000000
    为什么会是这样的呢?
    原因就是由于float的精度,把float转成double后,可以看出它只是近似等于4.6,而为4.59999990463257000000000000,当它*10显式转为int时,会以double的形式转换,即:(int)45.9999990463257,当然是45了。但是,用(int)(float)(k1*10)或k1=k1*10后转换,将会以float的形式显式转为int,结果是46。float的精度问题不但在乘法中存在,在其他运算中也是存的。以上的代码也证实了这点。所以,如果没有特别要求的话,数据运算还是用double类型为好。对于浮点数运算的结果是double,还是float,微软是这样说的:
        可在一个表达式中兼用数值整型和浮点型。在此情况下,整型将转换为浮点型。根据以下规则计算表达式: 
        如果一种浮点型为 double,表达式计算为 double 类型(在关系表达式或布尔表达式情况下为 bool)。 
        如果表达式中不存在 double,它将计算为 float 类型(在关系表达式或布尔表达式中为 bool)。 
      

  22.   

    TO:Ivony() 
    首先,我被你骂是我活该!

    float * float = float;
    float * int = int * float = float;
    好像也不一定呀!
    有时好像会是double的。但“至少”会是float。你如何解释(int)(4.6f*10)=45,而(int)(float)(4.6f*10)=46呢?
    而且,即使(int)(4.6f*10f)也是等于45,如何解释呢???请看下面的说法:
    如果二元运算符的一个操作数为浮点型,则另一个操作数必须为整型或浮点型,并且运算按下面这样计算:如果一个操作数为整型,则该操作数转换为另一个操作数的浮点型。然后,如果任一操作数的类型为 double,则另一个操作数转换为 double。至少用 double 范围和精度执行运算,结果的类型为 double(对于关系运算符则为 bool)。 否则,至少用 float 范围和精度执行运算,结果的类型为 float(对于关系运算符则为 bool)。
      

  23.   

    顺便插一句,关于上面有人提到的四舍五入的问题
    在C#里(其实是微软所有的语言里,其它公司的语言不太清楚)
    四舍五入实际上是按照国际标准的“四舍六入五成双”原则来进行的
    也就是说舍或者入以后,要保证最后一位是偶数
    所以 
    Math.Round(2.5, 0) = 2
    Math.Round(3.5, 0) = 4
      

  24.   

    在进行到int的转换时,一个是先将4.6f转换成int再乘。一个是先乘再转换。
    嘿嘿..............
      

  25.   

    怎么可能是将4.6先转换成int呢?如果那样结果就是40了。个人猜测:(无任何根据)
    微软将(4.6f*10)的结果作了优化。而(int)(4.6f*10)被当作一个表达式处理,还没来得及优化就转换成int了。
      

  26.   

    怎么可能是将4.6先转换成int呢?如果那样结果就是40了。个人猜测:(无任何根据)
    微软将(4.6f*10)的结果作了优化。而(int)(4.6f*10)被当作一个表达式处理,还没来得及优化就转换成int了。==========================================================这样也不能说明楼主的情况。
    有两个猜测:猜测一,是生成的IL不同,IL的JIT编译优化上面也许出了问题即:k1 = (k1 * 10);
    优化成了:
    k1 *= 10f;而
    k1 =(int)(k1 * 10);
    也许是优化成:
    kk = k1 * 10;
    k1 = (int) kk;
    这样两个运算的二进制代码是不同的。不过下面这个猜测也许更可靠:在float在进行计算的时候,.NET为了保持较高的计算精度,会自动将他们转成double来计算,在计算完后再转换回去。
    即:
    k1 = (k1 * 10);
    实际上是:
    k1 = (float) ( (double) k1 * (double) 10 );而
    k1 =(int)(k1 * 10);
    则会优化成:
    k1 = (int) ( (double) k1 * (double) 10 );从double->float->int之间的转换导致了这个问题。
      

  27.   

    TO:Ivony() 
    首先,我被你骂是我活该!

    float * float = float;
    float * int = int * float = float;
    好像也不一定呀!
    有时好像会是double的。但“至少”会是float。========================================================
    这个我想过,但是如果是double:
    k1 = k1 * 10就会是语法错误,因为float不能隐式的转换成double。
      

  28.   

    应该是double不能隐式的转换成float。
      

  29.   

    现在我还是有点不明白,请看下面的代码
    this.Response.Write("3: "+((k1*10)).ToString("0.0000000000000000000000000000000")+"<br>");
    它的结果是:3: 46.0000000000000000000000000000000,可见,(4.6f*10)的结果是46,即这个结果是float,但是(int)(4.6f*10)的结果是45,即这种情况下)(4.6f*10)的结果是double的,为什么会这样呢???
      

  30.   

    IL 最能说明问题:
    C# 代码(方法 Main() )
    static void Main()
    {
        float k1;
        int k;
        k1 = 4.6f;
        k = (int)(k1 * 10);
        Console.WriteLine(k);
        k1 = 4.6f;
        k1 = k1 * 10;
        k = (int)k1;
        Console.WriteLine(k);
        Console.ReadLine();
    }IL 代码(方法 Main).method private hidebysig static void  Main() cil managed
    {
      .entrypoint
      // 代码大小       54 (0x36)
      .maxstack  2
      .locals init (float32 V_0,               // 这里应该是变量声明吧?
               int32 V_1)
      IL_0000:  nop
      IL_0001:  ldc.r4     4.5999999           // 4.6f; 看看存成什么了    
      IL_0006:  stloc.0                        // 保存变量到 k1
      IL_0007:  ldloc.0                        // 读取变量 k1  
      IL_0008:  ldc.r4     10.                 // 将 10 转换为实形 10 -> 10.
      IL_000d:  mul                            // 乘法 4.59999 × 10. -> 45.999
      IL_000e:  conv.i4                        // 结果直接转换为整型 -> 45
      IL_000f:  stloc.1                        // 保存变量到 k
      IL_0010:  ldloc.1                        // 读取变量 k
      IL_0011:  call       void [mscorlib]System.Console::WriteLine(int32) // 输出
      IL_0016:  nop
      IL_0017:  ldc.r4     4.5999999           // 4.6f; 看看到底是什么
      IL_001c:  stloc.0                        // 保存到变量 k1
      IL_001d:  ldloc.0                        // 读取变量 k1
      IL_001f:  ldc.r4     10.                 // 将 10 转换为实形 10.
      IL_0023:  mul                            // 乘法 45.9999
      IL_0024:  stloc.0                        // 保存变量到 k1 45.9999
      IL_0025:  ldloc.0                        // 读取变量 k1   
      IL_0026:  conv.i4                        // 转换为整型
      IL_0028:  stloc.1                        // 保存到 k
      IL_0029:  ldloc.1                        // 读取 k
      IL_0029:  call       void [mscorlib]System.Console::WriteLine(int32) // 输出
      IL_002e:  nop
      IL_002f:  call       string [mscorlib]System.Console::ReadLine()
      IL_0034:  pop
      IL_0035:  ret
    } // end of method Tester::Main系统处理浮点数时,会处理精度问题,例如调用 System.Console::WriteLine(float32) 所以输出 46;转换为整型时,精度丢失,所以为 45
      

  31.   

    可见, 4.6f * 10 = 45.99999f 如果以 float 格式输出,则会进行精度调整,输出 46如果以 (int)45.9999999  输出,即整型输出,则会先进行转换,截断小数点后的内容:45.9999999 -> 45,所以输出 45。ToString() 输出也一样,因为 int.ToString() 和 float.ToString() 的方法是不同的!!以上 IL 为 .Net 2.0 的编译结果(没有使用任何编译参数)。测试楼主的代码得到两个 45 ……