float转int 四舍五入问题

http://blog.csdn.net/ropai/article/details/19907847

   最近碰到一例客户投诉某款产品某个参数显示误差的问题,经检查发现是软件中浮点数(float)转化为整型数(int)时候未四舍五入造成的。

    虽说是小问题但也值得重视,如果是航天飞机/月球探测仪(纯属YY)的软件中出了误差可能后果不堪设想。

 

  1. /**  
  2. <span style="font-family: Arial, Helvetica, sans-serif;">  问题重现, float强制转化为int, C代码片段 
  3. </span><span style="font-family: Arial, Helvetica, sans-serif;">**/  
  4. </span><span style="font-family: Arial, Helvetica, sans-serif;">int i;  
  5. </span><span style="font-family: Arial, Helvetica, sans-serif;">float f = 12.52;</span>  
  1. i = (int)f;    /*  强制转化 */  
  2. printf("i=%d", i);  
这里的i打印出来为12,因为强制转化是直接截掉小数部分的。


如果要四舍五入转化为int咋办?

自己写个floatToInt()就可以了,注意正负数区别


  1. int floatToInt(float f){  
  2.     int i = 0;  
  3.     if(f>0) //正数  
  4.       i = (f*10 + 5)/10;  
  5.     else if(f<0) //负数  
  6.       i = (f*10 - 5)/10;  
  7.     else i = 0;  
  8.   
  9.     return i;  
  10.   
  11. }  

题外话:

      float数如何0的比较,if(f==0)?

      显然是不行的,有这么傻帽的笔试题吗:)

     


he answer there suggests the use an expression like

(int)(x+0.5)
but admits that this technique does not work for negative numbers. Moreover, it would be wiser to use  long  instead of  int

The following explains the issue in more depth.

First, the answer depends on what kind of conversion is desired: truncating or rounding. On the other hand, it essentially does not depend on the floating-point type from which you are converting - it might be float or double or even long double.

Sometimes people think they know that the value of a variable of a floating-point variable is exactly representable as an integer. You may believe that the value of x is 100.0 and you just want it type converted to type int, with value 100. But you should never rely on expectations about a floating-point value exactly equaling to an integer. What you probably need in fact is rounding conversion.

Truncating conversion means that any fractional part is discarded, so that e.g. 3.9 is converted to 3. Such a conversion is the default floating to integer conversion in C in the sense that it is applied whenever a value of a floating-point type (float, double or long double) is to be converted to an integer type. There are specific rules which describe when such a conversion takes place. Here we will only state that conversion occurs in an assignment like

                i = x
where i is of an integer type and x is of a floating-point type. Conversion also occurs, of course, in explicit type casts like
                (int) x
Rounding conversion  means that we get the integer which is nearest to the floating-point value, so that e.g. 3.9 is converted to 4. This is usually what people want when they ask the question we are dealing with. There is no direct tool (like an operator or a library function) for rounding conversion, and strictly speaking a rounding conversion is not a conversion in the same sense that those conversions which are defined in the C standard.

For positive floating-point values, the simplest way to achieve a rounding conversion is to use an expression like

                (long) (x+0.5)
but it is better to be prepared for negative values, even if you do not expect them to occur. This means that one should use the conditional expression
x >= 0 ? (long)(x+0.5) : (long)(x-0.5)
The value of this is expression is the integer which is nearest to the value of the floating-point value of x.

One can of course write a macro like

#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
if one needs rounding conversions a lot or wishes to make code somewhat more readable.

Notice that this means that the rounded value of 1.5 is 2 and the rounded value of -1.5 is -2. You might wish to have some other treatment for a value which is exactly between two integers. The issue is, however, not very important practically.

Beware that a conversion of a floating-point value to an integer can cause overflow and that most implementations give no diagnostic in such cases. Using long instead of int may (or may not) give you a wider range of integers, but it is still smaller than the range of floating-point numbers. (Using long is recommendable.)

If efficiency is not crucial, it is a good idea to make your program more robust by defining (instead of the simple #define above) the function

   long round(double x) {
      assert(x >= LONG_MIN-0.5);
      assert(x <= LONG_MAX+0.5);
      if (x >= 0)
         return (long) (x+0.5);
      return (long) (x-0.5);
   }
or, if efficiency is crucial, the macro
#define round(x) ((x) < LONG_MIN-0.5 || (x) > LONG_MAX+0.5 ?\
error() : ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
This requires that you have  #include <limits.h>  and that you have an error handling routine called  error  which is a function of type  long .



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值