日期:2014-05-20  浏览次数:20683 次

java之基本类型问题知识点
Java面试题之基本类型1. 截尾和舍入先来看看面试题:
public class baseType {
public static void main(String[]args){
float floatNumber =29.7f;
int intNumber =(int)floatNumber;
System.out.println(intNumber);
double doubleNumber = 29.7;
intNumber =(int)doubleNumber;
System.out.println(intNumber);
  floatNumber =29.3f;
intNumber =(int)floatNumber;
System.out.println(intNumber);
 doubleNumber = 29.3;
intNumber =(int)doubleNumber;
System.out.println(intNumber); 

}
}
答案:29,29,29,29
在java中,这种基本类型中精度间的转换都遵从一种称为“窄化转换”的原则。
因此在float或者double转型为整型值时,总是对数字执行截尾。而不是想当然的执行四舍五入。Java的类型转换在下面会详细解释。
以下说说还有一个比较有常用的的截尾方法。这个方法经常出现在java面试题的综合帖里面的,经常泡论坛的估计都能看到。
相信下面这道面试题大家都会见过:
Public class Test{
  public static void main(String[]args){
  System.out.println(Math.round(12.5));
  System.out.println(Math.round(-12.5));
   
}
}
直接看看JDK的源码:
public static long round(double a) {
return (long)floor(a + 0.5d);
}
看到了没有在调用floor的时候无论 a 是否是正负数,都给a加上0.5.
floor这个方法最终的调用还是调用StrictMath.floor(a),
trictMath.floor(a)这个方法是jdk的本地方法,我没有查到他的具体代码,但是估计这个是通用的函数来的,类似于C++的函数库中的一样。根据C++的函数库floor的解释:
返回不大于改参数的最大整数(最接近正无穷)的double型值。
所以这个很容易解释上面的结果了。即使是
 System.out.println(Math.round(12.0));
 System.out.println(Math.round(12.4));
结果都是一样的:12。
因为返回的结果都是不大于输入参数加上0.5的最大整数而已,关键词是不大于。
2. 精度转换1.float型float f=3.4是否正确? 

答案:很明显是不正确。精度不准确,应该用强制类型转换,如下所示:float f=(float)3.4 或float f = 3.4f。在java里面,对于语句中出现的常数,没小数点的默认是int,有小数点的默认是 double;
2.short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
答案:short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1)。short s1 = 1; s1 += 1正确。
在JAVA规范上,e1+=e2 实际上是 e1=(T1)(e1+e2),其中T1是e1的数据类型s1+=1等效于 s1=(short)(s1+1),所以是正确的。
还有一道题,来自深入虚拟机的。
class BadArithmetic{
static byte addOneAndOne(){
  byte a = 1;
  byte b = 1;
  btye c = a+b;
  Return c;
}



初看,好像没有什么错误,其实会报一下错误的。 Incompatible type for declation·····错误的。在虚拟机内部,涉及到byte,short和char类型的运算操作首先会把这些值转换为int类型值的,然后对int类型的值进行运算,最后得到的结果也是int类型的结果。因此如果两个byte相加,得到的结果是int类型的,如果需要得到byte的结果,就必须显示的进行类型转换:byte c =(int)a+b;如果将正确的代码产生class文件并分析这些文件,就会发现: 有以下的 虚拟机汇编语句:iadd---------i2b.iadd语句意义为执行int类型的加法,因为 a和b在压入方法栈的时候,就变成了int类型的值了。i2b的意思正如语句一样就是讲int类型的值转换为byte类型。每一种类型转换都有对应的汇编指令。Java虚拟机中不能把long,float,double类型的值直接转换为比int类型更小的类型,原因在于
虚拟机中没有对应的操作指令。因此,把foat转为byte需要两个步骤。一,先将float转为int类型的,然后将int类型转为byte类型。
再看看下面的一道题:
public class TestRound {

/**
 * @param args
 */
  public static void main(String[]args){
   
  System.out.println(3.3f-2.4f); 
  float c = 0.9; 
  System.out.println(c);
   
}
 
答案是否觉得很奇怪呢?
有人会问,为什么
Java代码  
1 System.out.println(0.9f);  

输出的还是0.9呢?
因为在源代码里面println调用的是Float#toString(float),最终的实现是在
Java代码  
  public static String toString(float f) {  
  return new FloatingDecimal(f).toJavaFormatString();  
}  

下面实战计算一把:
3、浮点型的减法运算
浮点加减运算过程比定点运算过程复杂。完成浮点加减运算的操作过程大体分为四步:
  (1) 0操作数的检查;
如果判断两个需要加减的浮点数有一个为0,即可得知运算结果而没有必要再进行有序的一些列操
作。
   (2) 比较阶码(指数位)大小并完成对阶;
两浮点数进行加减,首先要看两数的 指数位 是否相同,即小数点位置是否对齐。若两数 指数位 相同,表示小数点是对齐的,就可以进行尾数的加减运算。反之,若两数阶码不同,表示小数点位置没有对齐,此时必须使两数的阶码相
同,这个过程叫做对阶 。
如何对 阶(假设两浮点数的指数位为 Ex 和 Ey ):
通过尾数的移位以改变 Ex 或 Ey ,使之相等。 由 于浮点表示的数多是规格化的,尾数左移会引起最高有位的丢失,造
成很大误差;而尾数右移虽引起最低有效位的丢失,但造成的误差较小,因此,对阶操作规定 使尾数右移,尾数右移后使阶
码作相应增加,其数值保持不变。很显然,一个增加后的阶码与另一个相等,所增加的阶码一定是小阶。因此在对阶时,总是
使小阶向大阶看齐 ,即小阶的尾数向右移位 ( 相当于小数点左移 ) ,每右移一位,其阶码加 1 ,直到两数的阶码相等为止,
右移的位数等于阶差 △ E。
   (3) 尾数(有效数位)进行加或减运算;对阶完毕后就可 有效数位 求和。 不论是加法运算还是减法运算,都按加法进行操作,其方法与定点