前几天天遇到一个问题,就是在显示浮点数值时,读到的数和输出的数不一样,比如说,我读到float 14.7,然后要按每一位分别输出,结果输出为14.6,开始以为是程序写的有问题,检查一遍后发现应该逻辑上是正确的。后来问了老师,解释这是有限字长效应, (百度解释:运算过程中的有限字长效应与所用的数制(定点制、浮点制)、码制(原码、反码、补码)及量化方式(舍入、截尾处理)都有复杂的关系。例如,使用定点制时,每次乘法之后,会引入误差;而浮点制时,每次加法和乘法之后均会引入误差。) 32位浮点数的14.7实际上真正的值应该是14.69....(后面N位省略),所以在我的程序运算中,结果便成了14.6。 解决办法:将得到的数值最末位的后一位加5,就可以保证数值的最末位在输出时不会减小。比如14.7,实际在机器中读到的应该是14.69....(后面N位省略),在此姑且认为是14.69,按位取数的时候,整数位14是对的,但是如果直接取小数位7的话,理想情况是用((int)(0.7*10))%10=7,但实际上的运算是应该是((int)(0.69*10))%10=6,得到的是6。 解决之后,(int)14.69=14,得到整数位,那么用14.69*100+5=1474, 用1474--14*100=74,这时再用(int)(74/10)=7,得到小数位7。 原来的程序: //带小数的数值的显示,val表示数值,valid_bit表示小数位数 void SvgNum::setVal(float val,int valid_bit) { int a; a = int(val); float b; b = val - a; //b得到val的小数位 int i; for(i=0;i<valid_bit;i++) b = b * 10; int c; c = int(b); int temp = c; //写小数部分 for(i= m_numberBits-1; i>=valid_bit-1 ; i--) { cellnumval[i] = temp % 10; temp = temp / 10; } if (valid_bit >m_numberBits-1) return; cellnumval[m_numberBits-1-valid_bit] = '.'; //设置小数点位置 temp = a; if(valid_bit>=m_numberBits-1 ) return; // 如果小数位数大于等于>=(显示位数-1),则直接返回 //写整数部分 for(i=m_numberBits-2-valid_bit ; i>=0 ; i--) { cellnumval[i] = temp % 10; temp = temp / 10; } 修改后: void SvgNum::setVal(float val,int valid_bit) { int a; a = int(val); float b; b=((val*100+5-a*100)/10); int i; int c; c = int(b); int temp = c; for(i= m_numberBits-1; i>=valid_bit-1 ; i--) { cellnumval[i] = temp % 10; temp = temp / 10; } if (valid_bit >m_numberBits-1) return; cellnumval[m_numberBits-1-valid_bit] = '.'; temp = a; if(valid_bit>=m_numberBits-1 ) return; for(i=m_numberBits-2-valid_bit ; i>=0 ; i--) { cellnumval[i] = temp % 10; temp = temp / 10; }