main()
{int a=100,b;
float u=1.9f;
b=u*a;
printf("%d",b);
}
为什么结果是189,而不是190?
另外当u=1.7f时,或者其他的什么数字,一般都正确。
还有很多*.9这样的数字也是这样的,请问如何解决?
如果使用(int)u*a;进行转换;
我是在使用对话框中遇到这个问题的,如果用户输入一个u=1.9f,a=100,我需要在另一个文本框里显示190,如果是189,那客户岂不会把你骂死?

解决方案 »

  1.   

    浮点数不精确,
    当你写 float u=1.9f; 时,u 里面存放的实际是1.899999999999用double就好了int main()
    {
        int a=100,b;
        double u=1.9;
        b=u*a;
        printf("%d",b);
        return 0;
    }
      

  2.   

    main()
    {int a=100,b;
    float u=1.9f;
    b=(u+0.000001)*a;
    printf("%d",b);
    }
      

  3.   

    main()
    {int a=100,b;
    float u=1.9f;
    b=u*a;
    printf("%d",b+0.5);
    }
      

  4.   

    用Double可以,
    u+0.000001或者b=(u+0.000001)*a+0.5都可以
    "%d",b+0.5是不行的。问:变为整数的时候,好象是去尾的,如何改变默认的去尾为圆整到一个最接近的整数呢?
    VC6中是否可以实现?请参考http://www.dracat.net/~wyvern/papers/floatcast.pdf;
    以下是引文:
    Intel Float Casting
    Wyvern Aldinger
    One-Way Overhead
    A little bit of esoteric geek-knowledge that came up recently was how fast is it to do floating point to integer
    conversions in C or C++. The answer is, on an Intel anyway, expensive.
    Integer to floating point is not bad. Let’s say you write the following C++ code:int i;
    float f = static_cast<float>(i);This becomes just two floating-point operations: one to load an integer into a floating point register, the other to write that register back to memory. According to my assembly language reference1 this takes about17 cycles on an 80486.
    The problem is in going the other way. If you naively do this in C++:
    float f;
    int i = static_cast<int>(f);
    This becomes a whole string of assembly, often involves a function call, flushes the CPU pipeline twice, and basically has a lot of overhead.
    Reason
    There is so much work to converting a float into an int because of the number of ways in which it can be done. You might think of rounding a float towards zero, away from zero, towards infinity, towards negativeinfinity, or towards the nearest integer. The C specification takes the mystery out of this by defining that casting a float to an integer truncates the floating-point modulus, effectively rounding towards zero.
    However, this is not the Intel hardware default.The Intel x86 Floating Point Unit (FPU) has a set of bits called the control word that determines, among other
    things, rounding and truncation. By default, this control word is set to round to the nearest integer.
    So when your C compiler has to do a typecast from float to int, it really involves the following steps: &#61472;Read the FPU control word into a memory location
     &#61472;Read that memory location into a CPU register2
     &#61472;Modify the control word
     &#61472;Store the copy back into a second memory location
     &#61472;Load the modified control word from memory into the FPU
     &#61472;Store the floating point number being converted from the floating point register stack into the
    destination integer in memory
     &#61472;Load the original control word from memory into the FPU, thus restoring the original state
    That is a very large amount of work. It is not difficult to do better.1 Microsoft MASM 6.1 Reference, Microsoft Corporation, 1992.
    2 There is, with one exception, no way to move data directly from the FPU registers into the CPU registers.
    Refinement
    Using inline assembly language in Microsoft Visual C++ 6.0, I implemented new versions of a Round() and
    a Trunc() function. I then tested these against more traditional implementations of the same functions that used the compiler’s own typecasting. Tests were run both with and without compiler optimizations. After factoring out the common loop overhead, the new versions of these functions ran in about 26% of the time needed by the C cast versions.
    At the loss of some accuracy, further refinement was still possible. The Intel rounding method is not quite exact in that half-integers are rounded toward zero instead of away. For instance, 0.4 and 0.5 are both rounded to 0, while 0.6 rounds to 1. If this behavior is acceptable to an application, an extra conditional can be removed from the new Round() method, yielding even better performance. I called this new version RoundFast().
    Approximate running time for each function is shown below in the table.
    New Functions Na&iuml;ve C Functions
    Trunc( ) 28% 100%
    Round( ) 23% 100%
    RoundFast( ) 19% -Finish
    The C++ and inline assembly implementations of each function are included at the end of this document.
    On a cautionary note, be aware that these new methods rely on the FPU control word being already set to do rounding rather than truncation. Since this is the default state, and as was already described most compilers will go far into the realm of ridiculous to preserve the settings, I feel this is a fairly safe assumption.
    Thanks go to Jonathan Shade for pointing out this issue to me and describing the reason why it happens.
    The code is my own though, so don’t hassle him with any bugs. _
    Implementation
    Na&iuml;ve C++inline float Trunc( float x ) {
    return static_cast<float>(static_cast<int>(x));
    }
    inline float Round( float x ) {
    x = (x < 0.0) ? x-0.5f : x+0.5f;
    return static_cast<float>(static_cast<int>(x));
    }New Versions
    // FLT_EPSILON is the smallest number on some system such that
    // a + FLT_EPSILON != a
    // It is defined in the header <float.h> or <cfloat>
    #include <cfloat>
    inline float Trunc( float x ) {
    x = (x < 0.0) ? x+0.5f-FLT_EPSILON : x-0.5f+FLT_EPSILON;
    int i;
    _asm {
    fld x
    fistp i
    fild i
    fstp x
    }
    return x;
    }
    inline float Round( float x ) {
    x = (x < 0.0f) ? x-FLT_EPSILON : x+FLT_EPSILON;
    int i;
    _asm {
    fld x
    fistp i
    fild i
    fstp x
    }
    return x;
    }
    inline float RoundFast( float x ) {
    int i;
    _asm {
    fld x
    fistp i
    fild i
    fstp x
    }
    return x;
    }